$Revision: 1.15 $
Copyright © 2004 Infiscape Corporation
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with the Invariant Sections being Appendix D, GNU Free Documentation License, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in Appendix D, GNU Free Documentation License.
Table of Contents
List of Figures
List of Tables
Table of Contents
Since its inception, VR Juggler has been designed to be highly flexible and dynamic. At the heart of this is the high degree of configurability present in VR Juggler. In spite of being a fundamental aspect of using VR Juggler, configuration of VR Juggler has always been difficult. Through this book, we will present VR Juggler configuration in a way that will make the process more approachable and that will enhance understanding of VR Juggler as a whole. We begin by examining the basic aspects of the VR Juggler configuration system, encapsulated within the JCCL module, and we then provide high-level explanations of how to configure general pieces of VR Juggler. At the end of this book, the reader will find appendices that explain the configuration of specific devices. The appendices include tips and troubleshooting points to help with commonly encountered complexities.
A key feature of VR Juggler is its portability, both in terms of operating systems and in terms of immersive system. As a virtual platform for the development of virtual reality (VR) applications, VR Juggler facilitates the transition of VR applications from the desktop to the immersive system. It also aids in the migration of the application across a variety of immersive systems. VR Juggler achieves this degree of portability by separating the details of the immersive system from the application. Hence, those details can change without requiring any changes to the application.
To handle variations in immersive visualization systems, VR Juggler has been designed to be highly configurable. VR Juggler is not written to work with any specific type or classification of immersive system. Instead, it handles the general aspects common to all immersive systems in code while offloading the device-specific pieces to run-time configuration. The components of VR Juggler have been parameterized to ensure portability and scalability across a staggering variety of display and input hardware combinations.
Component parameterization is captured within configuration elements, or simply “config elements.” Understanding config elements is vital to understanding the process of configuring VR Juggler. Throughout this text, we will discuss config elements and their utility as the means for configuring VR Juggler.
A configuration element is the fundamental unit of configuration within VR Juggler. Each config element is composed of one or more properties and is identified by a user-specified name. Each property has a type such as string, integer, pointer, etc., and properties can have either a fixed number of values or a variable number (zero or more) of values. The conceptual structure of a simple config element is shown in Figure 1.1, “Simple Configuration Element”.
In the figure, we see that the property named Size has two values: width and height. The valid type for both values of this property is integer. In general, all the values of a given property will have the same type. While there are exceptions to this, we will not go into such details at this time. In nearly all current cases, remember that the values of a property all share the same type.
The list of valid types for properties is shown in Table 1.1, “Valid Property Types”. A basic understanding of the valid types and their run-time interpretation in C++ can be useful when entering values. For example, note that the property type “integer” can be interpreted as a wide variety of C++ integer types. In some cases, the component being configured may limit the range of valid integer values that can be accepted from a config element. Hence, it can be important to know what the range of valid values is for a given property.
Table 1.1. Valid Property Types
| Type | Valid C++ Interpretation |
|---|---|
| integer | int, unsigned int, long, unsigned long, long long, unsigned long long, short, unsigned short, char, unsigned char |
| float | float, double |
| boolean | bool, integer |
| string | std::string, char* |
| config element pointer | std::string, char* |
| config element | jccl::ConfigElementPtr |
The concept of a config element “pointer” reduces to simply the name of another config element. At run-time, the loaded config elements are stored in a table that is indexed by element name. This means that within a given configuration, all the elements must have unique names.
Note that the last entry in Table 1.1, “Valid Property Types” is “config element.” This means that config elements can be nested within other config elements. A nested config element is often called an embedded config element. There is no limit to the depth of config element nesting, but in general, config elements are rarely nested more than one level deep. Doing so can complicate user understanding of the configuration process. It is hoped, however, that continued improvements to the VR Juggler configuration editor will alleviate confusion related to nested config elements. For now, it is sufficient to understand that a nested config element is just another property type.
The specification of property types, the number of allowed values, and other structural aspects of config elements are defined by configuration definition , or simply “config definitions.” The relationship between config elements and config definitions is quite similar to that of objects and classes in object-oriented languages. A class defines structural and behavioral information, and an object is an instance of a class. At any time, there can be many instances of a single class, each referenced by a different variable. Similarly, a config definition defines structural information, and a config element is an “instance” of the definition. There can be many config elements for a given definition, and each config element is identified by its unique name. Config definitions even support a limited form of multiple inheritance.
Config definitions are found in files that are named based on the config element type defined therein and have the extension .jdef. To allow versioning of config elements, a given config definition may have many versions, each of which is identified by an integer value that is incremented each time a structural change is made to the definition. Config definitions are loaded by scanning directories listed in an environment variable. VR Juggler performs this scan before any attempt to load a config file is made to ensure that the run-time environment knows about all existing config definitions.
As one would expect, configuration elements are what provide the run-time configuration information for VR Juggler. A casual observer would say that VR Juggler is configured by the configuration files that are loaded at run time. In reality, VR Juggler is reconfigured by the individual config elements that are processed. As a whole, VR Juggler starts out with no configuration. With the help of the Configuration Manager, the VR Juggler kernel main loop performs what is known as run-time reconfiguration wherein the config elements read from the configuration file(s) given at run time are processed. This means that VR Juggler dynamically reconfigures itself over and over again until the kernel determines that no more reconfiguration can occur.
The Configuration Manager maintains three lists of config elements:
The Configuration Manager delivers individual config elements from the pending list to those entities within VR Juggler that accept them. These entities are known as config element handlers, and they normally register themselves with the Configuration Manager when they are created.
For each config element in the pending list, the Configuration Manager tests to see if the dependencies of the element are satisfied. With the presence of config element pointers, one config element may depend on one or more other config elements being processed first. In other words, if config element A depends on config element B, then B must be in the active list before A can be given to a handler. If it is determined that the dependencies for the config element are met, then the Configuration Manager delivers the config element to its handler. If the dependencies are not met, then the config element goes back into the pending list, and another attempt to process it will be made later.
When a handler receives a config element, it attempts to read the values from the individual properties and configure (or de-configure) itself. If the handler concludes that its configuration procedure was successful, the Configuration Manager moves the config element from the pending list to the active list. If the handler cannot process the config element correctly, the config element goes back into the pending list so that another attempt to process it can be made later.
In typical usage, the startup process of a VR Juggler application shows the reconfiguration process. Attempts are made to process config elements until the pending list reaches a state where it is considered “stale.” This means that a sufficient number of reconfiguration attempts were made with no config elements being processed. When all config elements are processed, a message similar to the following will be printed to the console where the application was executed:
[0002315/000] DBG:ConfigManager::pendingNeedsChecked: Pending list is now
STALE: 0 items still in the pending list
[0002315/000] DBG:---- Pending list: 0 items ----
----------------------------------
If there should be one or more config elements that are left unprocessed for some reason, then output similar to the following will be printed:
[0002333/000] DBG:ConfigManager::pendingNeedsChecked: Pending list is now
STALE: 1 items still in the pending list
NOTE: These items have been specified in the configuration
but have not been loaded.
This may be a problem in the configuration OR
it may be waiting for more configuration information.
[0002333/000] DBG:---- Pending list: 1 items ----
ADD -->My IS-900 type: intersense
----------------------------------
Most people getting started with VR Juggler interpret one of the above messages to mean that something about the application has “stopped.” In reality, nothing has stopped permanently. The kernel main loop is still running, but there is nothing new in the pending config element list to process. The above message may be printed again later if new configuration elements are added to or removed from the Configuration Manager.
Neither of the above output messages is an error message. Rather, both forms of the output state that the reconfiguration process has reached a point where there is nothing new to process. The longer form indicates one of two things: either the configuration had extra, unused config elements or the configuration is incomplete. In the latter case, that usually means that a config element did not have one or more dependencies met. As we will see later in this chapter, it is possible to satisfy missing dependencies without restarting the application.
The output from the VR Juggler configuration process can sometimes be misleading. Due to its dynamic nature, attempts and reattempts are made to configure components within VR Juggler. Thus, if something in the configuration fails early in the process, it may cause problems much later on. It is therefore a very common mistake to assume that the last message printed to the console, no matter what it says, is where a problem occurred. If some part of the configuration fails, there may be other error messages or warning messages printed early in the output that explain what caused the later failure. As a rule of thumb, if a problem occurs with the execution of a VR Juggler application, scroll up to see if there are errors or warnings printed to the console before concluding that the last message is related to the fatal error.
VR Juggler configuration files, or simply “config files,” are those files that end with the extension .jconf. They contain zero or more configuration elements, and they can reference other configuration files. The files themselves are stored in a format called XML, a text-based, and therefore cross-platform, file format.
In VR Juggler terminology, a configuration is a collection of config elements that provide a complete set of parameters needed to execute a VR Juggler application successfully. A configuration can be defined by one or more .jconf files, and .jconf files can be mixed and matched to give different configurations. The concept of a configuration is especially important within the context of the VR Juggler configuration editor, VRJConfig. We discuss VRJConfig more in the following section.
Ultimately, the concepts surrounding VR Juggler configurations are hierarchical in nature. Each piece of the configuration puzzle is composed of smaller pieces. The following summarizes the hierarchy starting from the smallest piece and going up from there:
Value: A storage unit capable of holding a single datum of any type.
Property: A property has zero or more values of the same type.
Configuration element: A config element is composed of one or more properties.
Configuration file: A config file contains zero or more config elements.
Configuration: A configuration is made up of one or more config files that together provide a comprehensive collection of settings for parameterized components in VR Juggler.
Since .jconf files are stored as plain XML, they can be edited manually using a standard text editor. While sometimes quick and convenient, this method is not recommended because it is very easy to make mistakes that break the configuration or that violate the XML syntax. Furthermore, editing configuration files by hand with a text editor retains the old mindset of testing configurations by running an application, shutting it down, changing the configuration, and running the application again. VR Juggler offers much more power and efficiency in terms of configuration editing than this. In this section, we introduce VRJConfig, the VR Juggler configuration editor, and we explain how it can be used for static and dynamic configuration editing. Since the theme of this book is configuring VR Juggler, it is important for us to explain VRJConfig. However, an in-depth usage guide is beyond the current scope of this document. We will explain the concepts present in VRJConfig and provide enough explanation of its usage to get readers comfortable working with it.
VRJConfig is the Java-based graphical user interface (GUI) for creating and editing VR Juggler configurations. A screen shot of the VRJConfig Configuration Editor is shown in Figure 1.2, “VRJConfig”. It is based on Tweek, an implementation of a distributed model/view/controller system. Without going into great detail about the Tweek Java API, it is sufficient to state VRJConfig exists as a collection of JavaBeans loaded by and executed within the Tweek JavaBean Loader.
The VRJConfig Configuration Editor represents the low-level, all-purpose editor. It is capable of editing any config element. The representation of a config element provided by this editor shows both the property values and the structure of the element.
It is important to understand, however, that VRJConfig strives to provide an interface for configuration editing as opposed to the lower level concept of property editing. As was noted earlier, .jconf files can be edited manually using an ordinary text editor. This approach would be considered property editing because the user concentrates on the values of individual properties without necessarily considering the whole config element let alone the whole configuration. With the VRJConfig Configuration Editor, the intention is to provide more of a big-picture view of a collection of config elements as a complete configuration rather than as an assortment of disparate property values.
The VRJConfig Configuration Editor utilizes a multi-document interface (MDI) paradigm. Each internal window is called a configuration context, or simply a “context.” Each context should be treated as a complete configuration to achieve proper use of VRJConfig. Throughout the discussion of configuration contexts, the main toolbar at the top of the VRJConfig Configuration Editor panel will be important. It is shown again in Figure 1.3, “VRJConfig Configuration Editor Main Toolbar” to distinguish it from the full editor GUI.
A new config context can be created either by opening an existing .jconf file or by creating a new .jconf file. In either case, a new internal window will open within the VRJConfig Configuration Editor. The main toolbar has buttons for creating a new .jconf file and for opening an existing .jconf file. They are highlighted in Figure 1.4, “VRJConfig Configuration Editor New and Open Buttons”.
Once the context is created, the view of VRJConfig will be similar to what was shown earlier in Figure 1.2, “VRJConfig”.
The purpose of a configuration context within VRJConfig is to facilitate the notion of editing a configuration as a whole. As such, adding more .jconf files to an open context is a common operation. Each context has its own toolbar that is independent of the main VRJConfig Configuration Editor toolbar, and this toolbar is what must be used to extend or modify the state of a given configuration context. The context-specific toolbar is shown in Figure 1.5, “VRJConfig Configuration Context Toolbar”.
On the left side of the toolbar, we see the usual icons for file creation, opening, and saving. To add a new .jconf file to the existing config context, either the or the button must be used. Using the or the button from the main VRJConfig toolbar will result in the creation of a new configuration context.
On the right side of the context-specific toolbar, we see a button with an icon that is a downward pointing arrow. This button is only active when there are at least two .jconf files open in the VRJConfig Configuration Editor as a whole. Clicking the button reveals a special menu shown in Figure 1.6, “VRJConfig Context Modification Menu”. In the menu, the selected .jconf files are those that are open in the current context. Selecting a file from the menu will add it to the current context. De-selecting a file removes it from the context. In this way, it is possible to build up config contexts using different config files.
With multiple configuration contexts open, it is often desirable to move or copy config elements around. The MDI paradigm helps make this possible by allowing multiple windows to be visible at once, and copy-and-paste support within the VRJConfig Configuration Editor completes the picture. Note, however, that the granularity of copy-and-paste operations—including drag and drop—is at the level of config elements. Individual properties cannot be copied between contexts or between config elements.
On the left side of each config context window is a tree view of the config element hierarchy (as seen in Figure 1.7, “VRJConfig Config Element Navigator Panel”). This hierarchy is a dynamically updating organizational model of all the config elements in the current configuration context. Within the tree, names shown in bold text are categories. Names shown in non-bold text are config element names. As config elements are added to and removed from the current context, the tree structure will change. Empty categories are not shown.
The config element hierarchy also depicts the hierarchy inherent in config elements. That is, the nesting of config elements within config elements is shown, too. This allows quick, direct access to nested config elements for property editing purposes.
Adding new config elements to a configuration context is easy. Simply click the button shown above the config element hierarchy; it is always active. When clicked, a dialog box is opened that is used for choosing the type of config element to add to the context. The list, shown in Figure 1.8, “Config Element Chooser”, displays the human-friendly names of all known config element types. Entering text into the field labeled Config Element Type causes the selection to jump to the first element matching the entered text. This search is a rudimentary, exact-match type of search.
For a more advanced search capability, click the tab labeled Search. The dialog box will change to what is shown in Figure 1.9, “Config Element Search Dialog”. Initially, the config element list is empty, but as soon as text is entered into the search field, all elements whose human-friendly identifier match the entered text will be displayed. This search supports sub-string matches of search terms. The Search tab is useful to users who know exactly what they want or who have an idea of what to look for. In Figure 1.9, “Config Element Search Dialog”, the user started entering the word window as a search term, and all three possibilities for window-related config elements were immediately displayed.
Once the element type is chosen, click the button. A new element will be created in the current context with all of its property values initialized to their default setting. If multiple files are open within the context, another dialog box will be opened asking the user for a destination file for the new element. The first thing to do after creating a new config element is to set its name. In the config element hierarchy, new elements are created with the name “CHANGEME” indicating that the name needs to be set. To rename the element, either double-click on its name or right-click on the name and choose the item from the popup menu.
In some cases, it is necessary to triple-click on the name of a config element in the hierarchy tree. This is because Java sometimes interprets a double-click within a tree as an expand/collapse command for that branch of the tree. To get the correct behavior every time, right-click on the name of the config element to get the popup menu and choose .
To remove a config element, click on its name within the hierarchy and click the button. Otherwise, right-click on the element and choose the item from the popup menu.
The largest panel in the configuration context window is devoted to editing configuration elements. The full config element selected in the element tree is shown in this panel. From this panel, the individual property values can be edited. The view shown in this panel is designed to illustrate the hierarchical structure of a config element. Panels are nested within panels to show the nesting of config elements within config elements. Multi-value properties are rendered using a layout that shows data grouping as opposed to nesting.
Editing properties with a fixed number of values is straightforward. Those that have a multiple values may need to be expanded to show the full list, but no extra steps are required to insert entries that can be edited. VRJConfig will always show the full number of values for this variety of property. For new config elements, it will fill in the default setting for each of the property's values.
Properties with a variable number of values are a little more tricky. This variety of property can have zero or more values set, and the default case is to have zero values set. As such, new values must be added before editing can take place. In Figure 1.10, “Editing a Property with a Variable Number of Values”, we see two highlighted buttons: one for adding a new value and one for removing an existing value. The button is always at the top center of the inset panel while the button appears on the right side of the inset panel. There will be one button per value present in the config element.
Editing a static configuration represents the usual configuration editing process. This means that configuration files are loaded from permanent into VRJConfig. When the editing is complete, the files are saved back to permanent storage to be loaded at a later time by VR Juggler. Following this procedure stays with the traditional configuration process, depicted as follows:
Create or edit a configuration.
Run an application to test the configuration.
Exit the application and go back to step 1 if more changes are required.
This process does not harness the full potential of VR Juggler. Through its run-time reconfiguration capabilities, VR Juggler can be reconfigured on the fly using VRJConfig as a remote configuration editing tool. That is, VRJConfig can connect to a running application and edit its configuration without requiring the application to be shut down and restarted. A full discussion of this topic is postponed until Chapter 5, Remote Run-Time Reconfiguration Using VRJConfig.
With this introductory information complete, we can now move on to configuring VR Juggler. The remainder of this book is devoted to specific configuration topics. In general, configuring VR Juggler means configuring two large pieces: inputs and displays. In Chapter 2, Configuring Input, we explain the process of configuring input devices, both physical and simulated. In Chapter 3, Configuring Displays, we move on to the topic of configuring displays. The appendices of this book are devoted to configuration of specific input devices. Those readers who are already familiar with the general configuration of inputs to VR Juggler can refer to the appendices to find device-specific configuration instructions and tips.
Table of Contents
Input is critical to all immersive applications. Without it, achieving a sense of immersion is nearly impossible. VR Juggler provides a very advanced, robust, and flexible input management system through the Gadgeteer Input Manager. The flexibility of the Input Manager is due in no small part to the parameterization of components such as device drivers and input device proxies, but there is no denying the fact that configuring input for VR Juggler is difficult. Evolving features of VRJConfig are simplifying the process, but a thorough understanding of the input configuration process is invaluable regardless of features and capabilities offered by VRJConfig.
In this chapter, we will provide all the information needed to understand the configuration of input within VR Juggler. Fortunately, the design of the Input Manager reduces the process of input configuration to the same three conceptual steps regardless of what input device is being used:
Configure the input device, physical or simulator
Configure one or more proxies that point at the physical device
Configure zero or more proxy aliases
In the real world, there may be as many as five actual steps, but the above three sum up the overall process to follow every time input is configured.
The release of VR Juggler 2.0 Alpha 1 in March 2003 brought with it a new feature: device driver plug-ins. Instead of statically compiling all device drivers into the Input Manager, device drivers could now be loaded on demand. In order for this to occur correctly, however, the Input Manager now had to be told what driver(s) to load. This is achieved by configuring the Input Manager using a config element.
The Input Manager config element has three properties: a driver search path, a driver DLL name, and a directory to scan for drivers to load. All three properties may have zero or more values, but at least one must have a value in order for the config element to be useful. Each of the three is explained in the following subsections.
The driver search path provides the Input Manager with a list of directories where driver DLLs may be found. This property has a default setting determined at the time when the Input Manager was compiled. Based on the current list of supported operating systems, the default search path will be one of three values:
$VJ_BASE_DIR/lib/gadgeteer/drivers: The default for Linux, Windows, Mac OS X, FreeBSD, and other platforms where only one binary type is supported.
On Windows, the default is actually %VJ_BASE_DIR%\lib\gadgeteer\drivers. Platform-specific path details such as this may be omitted in this document for brevity. Bear in mind that internal handling of paths by VR Juggler and its components is always done correctly for a given operating system.
$VJ_BASE_DIR/lib32/gadgeteer/drivers: The default for an N32 build on the IRIX operating system.
$VJ_BASE_DIR/lib64/gadgeteer/drivers: The default for an N64 build on the IRIX operating system.
Since the base collection of device drivers that come with Gadgeteer are guaranteed to appear in the default search path, there is usually no need to set a value for the Input Manager driver search path property. The search path is configurable to allow users to tell the Input Manager where to find drivers they have written themselves that appear outside the VR Juggler installation hierarchy. When one or more values are provided through the driver search path property, the default search path is always appended to the end of the list. This ensures that user-specified directories will always be searched first when loading drivers.
When setting the driver search path, environment variables are allowed. As with all uses of environment variables in VR Juggler configuration files, they must be specified using either the form ${ENV_VAR} or $(ENV_VAR). Using $ENV_VAR or %ENV_VAR% will not work in this case or any other case. Any environment variable may be used.
The driver DLL name property is used to name specific device drivers to load. The name of the DLL to load must be specified in a special platform-agnostic manner. Essentially, this form boils down to removing the file extension from the DLL name. For example, the Ascension MotionStar DLL may be named MotionStar_drv.so, MotionStar_drv.dylib, or MotionStar_drv.dll depending on the host operating system. Note that all three have a common base name: MotionStar_drv. In the configuration of the Input Manager, this common base name is the string to set for the property value. This aids with portability of configuration files and (we hope) reduces the mental overhead required to configure the Input Manager on different operating systems where conventions will almost certainly vary.
The driver scan path provides a mechanism for loading all the device drivers found in the named directory or directories. This behavior is very similar to the old Input Manager that knew about all the device drivers, but in this case, the drivers are not statically compiled into the Input Manager. Use of this property is helpful when there is no need or no desire to load drivers individually. Doing so increases the memory overhead of the Input Manager, but it dramatically reduces the possibility for configuration errors related to driver loading.
Try to avoid using the driver scan path with the loading of individually named DLLs. Doing so could lead to unpredictable, undesirable behavior if the scanning process finds a DLL already identified by the naming of a specific driver DLL.
As with the driver search path, environment variables can be used in the string value(s) provided for this property. Furthermore, there is no need to specify a platform-specific file extension for use when scanning a directory for device drivers. The file extension is determined at compile time based on the target operating system. The search criterion used by the Input Manager is that the files match the pattern *_drv.<ext> where <ext> is the platform-specific file extension set at compile time.
The configuration process for input devices depends on the specific device being configured. In general, there is very little overlap among the configurations of the various device drivers that come with Gadgeteer. There are some exceptions such as the need to name a serial port and baud setting for some drivers, but this is hardly enough to provide the basis for a general explanation of how to configure input devices for use with VR Juggler. Instead, we will concentrate on the two categories of devices supported by Gadgeteer: physical devices and simulator devices. The term physical device is somewhat ambiguous because simulator devices get their input from a keyboard and mouse, and a keyboard and mouse are certainly physical input devices. The critical distinction is that simulator devices mimic the behavior of physical devices such as six-degree-of-freedom (6DOF) trackers using input from a keyboard and/or a mouse. As such, the configuration of simulator devices is very different from that of physical devices, and that difference is worth deeper examination.
A key aspect that is common to all input devices handled by the Input Manager is that they define input sources of one or more input categories. The input categories currently supported by Gadgeteer are the following:
Analog: Data in a continuous range with well-defined minimum and maximum values. Applications receive the data as normalized values in the range 0.0 to 1.0 inclusive.
Digital: Discrete on/off input, usually corresponding to simple button presses and releases.
Digital glove: Distinct combinations of fingers.
Event window: Source of keyboard and mouse events from the native windowing system.
Gesture glove: Recognizable hand gestures based on knuckle angles.
Positional: Multi-degree-of-freedom tracker data. Up to six degrees of freedom are supported.
Thus, a given device, physical or simulator, will fall into one or more of those categories. That same device may provide multiple input sources for a given input category. For example, a game pad may have eight buttons and two joysticks that operate in two axes. That game pad defines eight digital input sources (from the eight buttons) and four analog input sources (from the two axes of the two joysticks). We will speak of input sources more abstractly in the following sections, so it is important to understand what we mean by this term before proceeding.
Physical devices are those that provide what is traditionally considered immersive input. Typically, such devices have multiple degrees of freedom and/or provide specific information about what the user is doing. For example, a glove device could provide data identifying a specific hand gesture that the user is making. By attaching a 6DOF tracker sensor to the glove, both the position of the hand and the gesture it is making would be available to an immersive application. Placing tracker sensors all over the user's body provides full-body position and orientation information.
In terms of the Gadgeteer Input Manager, physically devices have thus far been characterized as requiring a device driver plug-in. The driver implements in software the communication protocol with the hardware so that data can be read from the device and interpreted before being passed on to the VR Juggler application. As of this writing, it is certainly true that each supported physical device has its own device driver plug-in, but this may not always be the case. While this may not always be the case, it will be useful to remember this fact for the purposes of the topics presented here.
The process of configuring a physical device means configuring its device driver. As noted above, there is very little commonality in the process of configuring specific hardware devices, but it is vital to understand the importance of properly configuring a device driver as part of the overall input configuration. If the driver itself is not configured correctly, there is no way that the rest of the input chain can function properly. In other words, if the driver cannot read data from the input device, there will be nothing to pass on to the VR Juggler application. For instructions and tips on specific device configurations, refer to the appendices at the end of this book.
Since all physical devices do have a device driver plug-in, proper configuration of the Input Manager is absolutely critical. Configuration elements for device drivers are handled by the drivers themselves, and if the Input Manager does not load a required device driver, the config element cannot be processed[1]. As such, it is very important to remember to configure the Input Manager as part of configuring a physical device.
If individual devices are configured in separate .jconf files, include an Input Manager config element for loading the device driver in the same file as the driver config element. The Input Manager can be configured repeatedly, so there is no problem with having multiple Input Manager config elements as part of a complete configuration. Each Input Manager must have a separate name, however, or else one config element may overwrite another in the Configuration Manager's pending list. The config element names can be made unique by including the name of the driver being loaded. For example, a .jconf file loading the IBox driver could include an Input Manager config element named “Input Manager IBox.”
The configuration of simulator devices is much more involved than that required for physical devices. All simulator devices read data from a traditional desktop keyboard and mouse and translate the data into information that mimics the behavior of the various device types supported by the Input Manager[2]. To configure a simulator device, there are two pieces that must be configured: an event window and the actual simulator device. We explain this in more detail below.
Keyboard and mouse data are received using what are known as event windows in Gadgeteer terminology. In the terms of a given windowing system (Win32, the X Window System, or Aqua), an event window is simply a window. When speaking generally, we often refer to event windows as “event sources,” and the terms can be used interchangeably in the scope of the Input Manager. Event windows may be graphics windows, or they may be standalone windows that display nothing. The use of graphics windows as event sources is discussed in more detail in the section called “Graphics Window Input”. For now, we will concentrate on the concept of event windows in general. We will examine each of the properties individually.
Together, these properties define the dimensions of the window in pixels.
This two-valued property sets the origin for the window when it is opened.
In VR Juggler, the lower left-hand corner of the display is the origin for positioning windows. This is in contrast to the way some windowing systems work wherein the display origin is the upper left-hand corner.
This property defines the relationship between mouse movement within the window and the number of key presses registered by the event window. The notion of a key press in the context of a mouse is counter-intuitive, and an in-depth explanation of what this means is beyond the scope of this document. We must explain, however, that event windows record input using the abstract concept of a key press. This corresponds to an event raised by the windowing system and handled by the platform-specific event window classes in Gadgeteer. The event window class records how many times an event was raised since the last time its data sample buffers were retrieved by the Input Manager. In the context of mouse movement, the interpretation of how much the mouse moved is based on the number of mouse motion events raised rather than the number of pixels the mouse pointer would have moved physically. Such behavior is necessary for recording input when the mouse is locked to the center of the event window. Setting the mouse sensitivity tells the event window how to interpret the mouse motion events. A value of 1.0 for this property indicates that one pixel of movement will correspond to one key press. A value of 0.1 says that ten pixels of movement translate to one key press. The default value is 1.0.
The “display number” property is used with windowing systems that define multiple displays on which windows can be opened. As of this writing, there is one such windowing system supported: the X Window System. The value set for this property is used as an index into an array of available displays defined in another config element called the Display System. The default value is 0, and this property will be ignored when using windowing systems that do not support multiple displays.
The “lock key” property defines a key that, when pressed, causes the mouse pointer to be locked to the center of the window. Such a capability is useful when it is necessary for the mouse to remain within the borders of the window at all times. The lock key also unlocks the mouse pointer when it is in the locked state. The default value is KEY_NONE which indicates that there is no key that toggles mouse pointer locking.
Related to the lock key, the “start locked” property indicates where the mouse pointer should be locked to the center of the window as soon as it opens. This setting defaults to false.
Each event window object handles events from the windowing system in its own thread. Depending on the nature of the windowing system, the event handling loop may never block on its own. To avoid the event window thread from starving all the other threads, this property sets a sleep time (in milliseconds) for the event window thread. Adjustment of this property may be necessary to get optimal behavior on a given computer. The default setting causes the event window sample loop to sleep 75 milliseconds between each event handling pass.
This property is used for configuring a cluster of graphics nodes. The topic of cluster configuration is addressed in the ClusterJuggler Guide.
Before we move on to the use of event windows as data sources for simulator devices, we should note that event windows can be standalone input sources for VR Juggler applications. As we will see in the section called “Device Proxies”, there is a proxy type and corresponding device interface through which applications can receive keyboard and mouse input. Hence, event windows can be considered as the middleman for giving applications access to the keyboard and mouse as physical devices. In this case, there is no special device driver to load.
With an event source configured, we can now configure a simulator device. The simulator device type to configure will be based on what is needed by the application. There are five simulator device types from which we can choose:
Simulated analog device: Provides a variable number of analog input sources in a configurable range based on two key presses (increment the value, decrement the value).
Simulated digital device: Provides a variable number of digital (on/off) inputs based on a single key press.
Simulated digital glove device: Provides a pair of digital inputs representing finger combinations from the left and right hand in a manner similar to a pair of Fakespace PinchGloves.
Simulated glove gesture device: Provides a variable number of gesture inputs in a manner similar to a Virtual Technologies CyberGlove.
Simulated positional device: Provides a single of 6DOF positional input source based on a combination of twelve key presses.
Below, we review each of these in detail and explain how to configure them in a manner that makes them easier for VR Juggler application users to understand. Before doing so, however, we must note that the config element for each simulated device type has a property for an event window proxy. Device proxies will be explain in detail in the section called “Device Proxies”, but for now, it will be helpful to keep in mind that the simulated device types do not refer directly to an event window. Instead, an extra level of indirection is introduced; namely, a proxy to the actual event window.
Furthermore, all simulated device types have key presses configured as key/modifier pairs. On a standard keyboard, there are alphanumeric keys (A-Z, 0-9) and modifier keys (CTRL, ALT, and SHIFT). A key/modifier pair is thus a combination of an alphanumeric key and a modifier key. Since mouse input is also considered a key press in the eyes of the Input Manager, a key/modifier pair may also be the combination of mouse movement and a modifier key or the combination of a mouse button press and a modifier key.
Simulated analog devices provide input values from a continuous, configurable range. At the application level, the input will be received as values normalized to occur in the range 0.0 and 1.0 inclusive. Each configured simulated analog device can provide zero or more analog input sources, each configured as a pair of key presses: one key press to increment the value and one to decrement it.
This property specifies a pointer to another config element of type event_window_proxy that in turn points to the event window from which keyboard and mouse input will be read.
This property defines a list of key/modifier pairs that are used to identify the key presses for incrementing the value of the analog input sources. There may be zero or more of these, and the amount must match the number of decrement key presses defined. The number of key presses defined indicates the number of analog data sources that this device has.
This property is the complement to the “increment key” property. It too specifies a list of key/modifier pairs that are used to identify the key presses for decrementing the value of the analog input sources. There may be zero or more of these, and the amount must match the number of increment key presses defined. The number of key presses defined indicates the number of analog data sources that this device has.
The “delta” property defines the change in the analog value per key press.
This property sets the minimum possible value for the device as a floating-point value. The default is 0.0.
This property sets the maximum possible value for the device as a floating-point value. The default is 255.0.
This property sets the starting value for the device as a floating-point value. This must be in the range [min, max]. The default is 0.0.
Note that a single simulated analog device shares the settings for the delta, range minimum, range maximum, and initial value across all its input sources. If there is a need to vary these settings, multiple simulated analog devices must be configured.
Simulated digital devices translate keyboard events and mouse events (both motion events and button presses) into digital input. A single simulated digital device may provide many digital input sources.
This property specifies a pointer to another config element of type event_window_proxy that in turn points to the event window from which keyboard and mouse input will be read.
The “digital button key” property defines a list of key/modifier pairs that provide digital input sources. There may be zero or more key/modifier pairs, and the number defined specifies the number of input sources that this device has.
Simulated digital glove devices mimic the behavior of gloves that have distinct gestures or finger combinations. Such gloves are usually in the same vein as the Fakespace PinchGlove where the glove sends a signal indicating which fingers are pressed together or are pressing a pad on the base of the palm. Gestures are identified as being either on or off. This is use is different enough from gesture recognition devices that a separate device type was created for it, but it is worth noting that a “digital” glove could act as a gesture recognition glove with the correct information provided to the Input Manager.
This property specifies a pointer to another config element of type event_window_proxy that in turn points to the event window from which keyboard and mouse input will be read.
This property defines a list of zero or more key/modifier pairs that provide digital values for each of the desired finger combinations. The number of input sources for this device will be determined by the length of this list. Digital device proxies (discussed later in the section called “Device Proxies”) will provide a more meaningful way of mapping the digital input source to a finger combination identifier.
This property sets a pointer to a position proxy that provides 6DOF tracker information for the left hand.
This property sets a pointer to a position proxy that provides 6DOF tracker information for the right hand.
As of this writing, gesture support in VR Juggler 2.0 is non-functional, so these devices cannot be utilized by VR Juggler applications. Until such time as gesture support in VR Juggler is completed, this section will not be filled in.
Simulated positional devices stand in for 6DOF trackers. Each has a unique 4×4 transformation matrix that can be used in traditional computer graphics computations. Unlike the previous simulated devices, one simulated positional device defines exactly one data source. To have n positional data sources for a VR Juggler applications, n simulated positional devices are required.
This property specifies a pointer to another config element of type event_window_proxy that in turn points to the event window from which keyboard and mouse input will be read.
This property has twelve values that define the key/modifier pairs that are translated into changes in the 4×4 transformation matrix held by the simulated positional device. For each degree of freedom, there are two key/modifier pairs defined: one to increment the value along or around an axis and one to decrement it.
This property has three values that specify the initial position in three-dimensional space of this positional device.
Similar to the “initial position” property, this property has three values that define the rotation about the X, Y, and Z axes for this device.
This property sets the change in translation per key press received from the event window. This value is in meters, and the default is a translation of 0.1 meters (10 centimeters) per key press. Translation occurs in the axis associated with the key being pressed.
This property sets the change in rotation per key press. The value is given in degrees, and the default is 1.0 degrees of rotation per key press. Rotation occurs about the axis associated with the key being pressed.
This property has two possible values: Local or Global. The value chosen indicates whether translations occur in the local coordinate frame or in the global coordinate frame. The default is the local coordinate frame.
This property has two possible values: Local or Global. The value chosen indicates whether rotations occur in the local coordinate frame or in the global coordinate frame. The default is the local coordinate frame.
This property defines zero or more position filters to apply to data received from this device. Position filters are covered in more detail in the section called “Position Filters”.
Device proxies introduce the layer of abstraction and indirection needed to ensure that VR Juggler applications do not become tightly coupled with specific devices. That is, a VR Juggler application cannot be written to work only with an Ascension MotionStar, for example, because device proxies prevent direct access to the underlying hardware device. Instead, the proxy acts as a pointer to a single data source from the actual device. Knowing this information will help with understanding how proxies are configured.
Earlier in the section called “Input Devices”, we listed the six device categories defined by the Gadgeteer Input Manager. Each of those device types has a corresponding device proxy type, as shown below:
Analog proxy
Digital proxy
Digital glove proxy
Event window proxy
Gesture proxy
Positional proxy
The config element for each proxy type has a property that points at an input device config element of the corresponding device type. For example, a position proxy config element can point at the config element for a simulated position device, an Ascension MotionStar, a Polhemus Fastrak, and so on.
The second property in every proxy type is a unit identifier. As we said in the section called “Input Devices”, each input device provides one or more input sources of a given input category. For example, an Ascension Flock of Birds with three sensors (birds) would provide three input sources in the positional data category. An Intersense IS-900 tracker with the usual head and wand sensors would provide two positional input sources, five digital input sources (five buttons on the wand), and two analog input sources (two axes on the wand joystick). The device proxy unit identifier acts as a zero-based index into the various input sources.
Putting all of this together, we find that we must have a unique proxy for each input source. Several proxies may point at a single input device, but each proxy config element will have its own name. The input device will have separate queues for its input source types, so the unit identifier property for each proxy must be set accordingly. For the IS-900 mentioned in the previous paragraph, we would have the configuration arrangement shown in Table 2.1, “Proxies for an Intersense IS-900”.
Table 2.1. Proxies for an Intersense IS-900
| Input Source | Proxy Type | Proxy Name | Unit Identifier |
|---|---|---|---|
| Head tracker | Position | Head Proxy | 0 |
| Wand tracker | Position | Wand Proxy | 1 |
| Wand trigger button | Digital | Button 0 Proxy | 0 |
| Wand red button | Digital | Button 1 Proxy | 1 |
| Wand yellow button | Digital | Button 2 Proxy | 2 |
| Wand green button | Digital | Button 3 Proxy | 3 |
| Wand blue button | Digital | Button 4 Proxy | 4 |
| Wand joystick x-axis | Analog | Joystick X-Axis Proxy | 0 |
| Wand joystick y-axis | Analog | Joystick Y-Axis Proxy | 1 |
Proxy aliases provide more abstract identifiers for use at the level of VR Juggler applications. In a VR Juggler application, there will invariably be at least one device interface object, and that object must be initialized with a symbolic identifier used by the Input Manager to connect the device interface with a proxy[3]. While the specific proxy name can be used, aliases offer some additional flexibility because a single proxy may have many aliases. For example, a device with three digital buttons would have three digital proxies pointing at it. Those proxies could be named “Left Button,” “Middle Button,” and “Right Button.” A VR Juggler application could be written to refer to Left Button directly, but that leads to the potential for tight coupling with a specific immersive system configuration. To help prevent this, some aliases could be created for the digital proxies. Those aliases could have names such as “Accelerate Button,” “Rotate Button,” “Stop Button.” Providing more symbolic names such as these facilitates the migration and adaptation of VR Juggler applications to different immersive systems.
When dealing with data from the sensors of a tracker, the positional information returned from a tracking system can be used directly, but many times the frame of reference for the tracker and/or its sensors is not the same as the real world. Because of this, the tracking data needs to be transformed into a common coordinate frame. This may sound complex, but what it means is that the coordinate system used by the tracker system is not the same as what VR Juggler applications expect. This is not because VR Juggler requires some certain coordinate system. Rather, the reason is that applications are generally written to expect the immersive system to use a standard coordinate system. If an application had to run in two different immersive configurations and one system had the x-axis going to the right while the other had the x-axis going up, the application would not behave consistently between the two. Before we explain how to manage all these coordinate systems, we must first define the notation that we will use. Once that is done, we will move onto the actual configuration aspects.
The description herein will make use of a specific matrix notation for transformations between various frames of reference. We have found this notation to be very useful for tackling transformation problems related to immersive applications. The original inspiration came from a VR systems book, and we have adapted it slightly for our purposes. The simple form of the notation is the following:
frame1Mframe2
Here, we use subscripts to represent the two frames of reference for the transformation. In this case, we say that the matrix transforms from frame1 to frame2. More specifically it moves the frame of reference from frame1 to frame2. If we are talking about transforming points (or other geometry), then the transformation would be as follows:
Pframe1 = frame1Mframe2 * Pframe2
Notice that we use the notation for points as well as matrices. The subscript of the point represents the frame of reference to which the point's coordinates are relative.
Some readers may be thinking that we have this backwards and that the matrix above moves from frame2 to frame1. From the perspective of the transformed points, this is true. From the perspective of transforming frames of reference, however, the matrix moves from frame1 to frame2. It is all a matter of perspective. The math will work out the same either way, and readers are encouraged to think about it whichever way seems more comfortable.
Where this notation gets interesting is what if we want to move from frame1 to frame3 and we have the following matrices:
frame1Mframe2, frame3Mframe2
We know that the matrix we want is frame1Mframe3, so the correct matrix is the following:
frame1Mframe3 = frame1Mframe2 * frame2Mframe3
This means that we must invert the frame3Mframe2 matrix in order to use it. This notation makes such details easy to identify since the frames of reference are part of the matrix name. We make use of this in the next section to keep track of which matrices to use at which times.
Figure 2.1, “Frames of reference for configuring a tracking system” shows a generic view of the coordinate frames at work in a standard tracking system. The details of this diagram are described below.
World coordinate system: The world coordinate system is the base coordinates of the real world system. In other words, this is the physical space of the immersive system. The coordinate system used depends upon local preferences, but normally for VR Juggler systems axis are X right, Y up, and Z out. Note that this is a right-handed coordinate system.
Tracker: The is the base frame of reference for the tracking system. This is normally defined by the "base unit" of the tracking system. For example, with an Ascension Flock of Birds tracking system, this coordinate frame is defined by the location of the transmitter (the large black cube).
Receiver: The is the coordinate system of the physical sensor (such as a bird in a Flock of Birds). Normally, people do not think of the receiver as having a coordinate system but instead think of it as having a position relative to the base tracker system. While this is true, that transformation actually defines another local coordinate frame for the receiver.
Tracked Object: The tracked object frame is a general name for the actual location that we are interested in tracking. In some cases, this is exactly the same as the Receiver, but this is not always the case. A common example of this is tracking the position of the user's eyes. Normally, people do not put a sensor exactly at the position of the user's eyes. Instead, the sensor is normally mounted on the side of a pair of glasses or a hat or some other object that the user wears on his or her head. In this case, the tracked object coordinate frame is at the location of the eyes.
When we configure a tracking system (and the associated position device proxies), we want to configure the system to return the correct tracked locations for the tracked objects in the environment. Computing this position involves the combination of multiple transformations. Just in the common case above, there are several transformations, shown below:
worldMtracker: This is the transformation that captures the location of the tracker base system in the real world.
trackerMreceiver: This is the reported transformation of the receiver. This is the only transformation that normally varies as an application is running and is the value that is returned by the tracking system.
receiverMtracked_object: This is the transformation from the position reported by the tracking system to the actual location that we want to track.
The value that the we want to configure the system to return is worldMtracked_object. This transformation is the location of the tracked object within the real world. To return this value we must compute the following:
worldMtracked_object = worldMtracker * trackerMreceiver * receiverMtracked_object
VR Juggler takes care of computing this value at run time, but as we stated earlier, the position of the tracker within the tracking coordinate system (i.e., trackerMreceiver) is the only value that normally varies at run time. The other two values must be configured in the tracking system configuration element. Fortunately, we have made this very easy to do in VR Juggler, and the description makes it sound much more complicated than the process really is.
Each object that can return position information (positional devices and position device proxies) can be configured with a set of position filters. The position filters are stored as a list of nested config element within the positional object's configuration element. Every physical positional device has this property in its config element. While the possibility exists for multiple types of filters, there exists only one at the time of this writing: the position transformation filter. This filter is used to add transformations to the positional object in a VR Juggler configuration. This filter type allows the configuration of pre-multiplying and/or post-multiplying the returned positional value by a user-defined transformation matrix. This is exactly what we need to configure a tracking system.
We will start by configuring the tracking device. As we can see from the equation above, we need to pre-transform the value returned from the tracking system (trackerMreceiver) by the position of the tracking system within the virtual world (worldMtracker). We configure this by adding a position transform filter to the “position filter” property for the tracking device config element and setting the values of the pre-translation and pre-rotation to this value.
All physical units for pre- and post-translation properties must be set in meters. There are no exceptions to this rule.
With the pre-translation and -rotation set up, we must also define the device units. The position transform filter config element has a property that identifies the scaling to apply to convert the units from the tracker into meters. The setting to choose depends on the tracker hardware, but if in doubt about the positional data being received by a VR Juggler application, try using the conversion from feet to meters.
To configure the tracked object positions, we need to configure the transformation applied to the position proxy for the tracked object (for example, the user head proxy). In this case, however, the transformation we need to apply is a post-transform of the value. In the config element for the positional device proxy, we must add a position transform filter to the “position filter” property and set the post-translation and post-rotation to the offset of the tracked object relative to the sensor being used to track the object.
When setting up the position transform filter for a positional device proxy, always leave the unit conversion factor set to meters (a value of 1.0). By the time tracker data gets to the proxies, it is already in meters, and converting it to anything else would lead to problems at the VR Juggler application level.
In the ideal case, the above process would work flawlessly every time, but this does not always happen. We have a couple of suggestions for how to deal with configuration problems of this sort. First, we find that drawing a picture of the all transformations can frequently help. Simply create a diagram that shows all the coordinate frames and the transformations between them. This can help in finding the one transformation that is not quite set correctly. Second, configure the immersive system one step at a time. Do not try to get both the tracking system transformation and the proxy transformation set all at once. Instead, work on getting the transformation correct for the tracking system first. Once this value is set, then start working on the proxy transformation. It is much easier to work on the configuration for a tracking system if only one value is changing at a time.
The previous section was purposely abstract in order to provide the conceptual background needed to understand the “what” and the “why” of configuring position filters. Ultimately, we care about the “how” of configuring position filters. As the name of this subsection implies, we will now put together all the concepts introduced above to explain concretely how to configure position filters. The following sub-subsections are essentially a step-by-step process for configuring the position filters used for the tracking system and its sensor(s).
Choosing the origin of the virtual world is the first step in defining how the immersive visualization system will work. Everything prior to this point relates more to how the Input Manager of VR Juggler works, but for the remainder of this book, our attention will be focused on configuring how we want the immersive system to work. Since the origin is the basis for configuring everything else, we must start with it.
The origin of the virtual world is a point in the physical space (the space of the VR system). The coordinate system rooted at this origin point is the World coordinate system shown above in Figure 2.1, “Frames of reference for configuring a tracking system”. Users of VR Juggler can configure the origin to be anywhere they want, but it is best to pick a point that makes sense. Most VR applications are going to orient their virtual space around the virtual world origin (it makes the math easier most of the time). In order to see all the important aspects of the virtual world, then, the origin must be positioned well[4]. The following are some tips for placing the origin:
For a projection system with a floor, a good place for the virtual world origin is at the center of the floor. This gives the user some room to move around physically, and it helps provide the user with a sense that s/he is at the center of the virtual space.
For a projection system with no floor, placing the origin is more difficult. Since the user will not be able to see what is below him or her in the virtual world, having the origin too far from the screen will cause objects in the virtual world to go out of view too easily. If the origin is behind the screen, the user may feel as though s/he is a spectator in the virtual space rather than an immersed participant. If the origin is above the floor (to compensate for a screen that is raised off the floor), the user will feel as though s/he always has to look up at the world from a low perspective―essentially from a bug's-eye view).
For a head-mounted display, the origin should be placed relative to the tracking system transmitter (or the emitter, depending on the terminology used by the manufacturer). For example, if the transmitter is suspended from the ceiling so that it is above the user, put the origin directly underneath the transmitter. If the transmitter is mounted from the floor, then put the origin somewhere directly in front of the transmitter.
Keep the origin within the tracked area. Application authors are likely to assume that the user starts using the application at the virtual world origin. If the origin cannot be reached physically by the user because it is outside the tracked area, this could reduce the functionality of the application in such a configuration.
Once the origin is chosen, then the pre-translation information can be entered into the tracker device position filter. This will tell the Input Manager how to transform data from the tracker into the coordinate frame of the virtual world, as described in the section called “Configuring Position Filters” and the section called “Putting it All Together”. Providing the pre-translation information is very simple. Measure from the physical location corresponding to the virtual world origin to the origin of the tracking system. Refer to the documentation of the tracking system to determine where its origin is (or how it may be set if it is configurable on the hardware side). Enter the measurements in meters for the pre-translation values (X, Y, and Z) of the position filter of the device configuration element. To put this another way, the pre-translation values entered for the tracking system transmitter correspond exactly with the position of the tracker in the virtual space relative to the origin of the virtual world.
Entering the orientation of the transmitter (the pre-rotation information in the position filter) can be a little more difficult. First, determine the coordinate frame of the transmitter. This is usually provided in the hardware documentation. Then, figure out how to rotate that coordinate frame so that it matches the VR Juggler coordinate frame. Remember that VR Juggler internally uses a right-handed coordinate frame with Y up. If it is possible to configure the coordinate frame of the tracker on the hardware side, it is typically easier to do this than to come up with the rotations needed to convert from the tracker coordinate frame to the VR Juggler coordinate frame.
Different graphics APIs have different coordinate frames. Do not consider such details when configuring VR Juggler. The VR Juggler Draw Managers worry about how to transform data from the internal VR Juggler coordinate frame into the coordinate frame of the graphics API. Users need never worry about such issues.
The tracked points are those that correspond to the sensors of the tracking system. There will always be a head sensor[5], and there is usually a sensor for one of the user's hands or for a wand-type device. Depending on how the sensor is mounted, it may be necessary to pick a point to track. For example, if a tracker is affixed to a pair of stereoscopic viewing glasses, it will probably be out of the user's line of sight. To get a good perspective (and hence, a good stereo effect), however, the tracked point should be right between the user's eyes. This will require a post-transformation on the proxy corresponding to the sensor.
Defining the post-translation and -rotation for a position proxy is mathematically different than the way that the pre-translation and -rotation are set up for the transmitter. In this case, we are operating in the coordinate frame of the sensor rather than that of VR Juggler. Therefore, we must first determine the coordinate frame of the sensor. Then, we measure from the sensor to the tracked point. The measurements (in meters) for the X, Y, and Z positions of the tracked point relative to the sensor are entered for the post-translation of the position filter for the proxy. To get the post-rotations, determine how to rotate from the VR Juggler coordinate frame (right-handed, Y up) to the coordinate frame of the sensor. Enter those rotations (in degrees) for the post-rotation of the proxy position filter.
Take careful notice of the way that this is reversed from the means for configuring the position and rotation of the tracking system transmitter. For the transmitter, we measured from the user-defined origin to the origin of the tracking system. Then, we rotated from the coordinate frame of the transmitter to the VR Juggler coordinate frame.
[1] An entry in the VR Juggler FAQ provides more information about this topic and addresses specific issues that users have encountered.
[2] For those unfamiliar with the functionality of the Input Manager, the supported device types are 6DOF positional, digital, analog, glove, and gesture. Refer to the VR Juggler Programmer's Guide for more information on this topic.
[3] For more information on the use of device proxies and device interfaces by VR Juggler applications, refer to the VR Juggler Programmer's Guide.
[4] Of course, many (most) applications will be written after the immersive system is configured, so application authors are likely to make assumptions about the position of the origin based on an existing configuration. For new installations that will be running existing applications, the choice of the origin placement may be more or less difficult depending on the needs of the applications.
[5] Even when the user's head is not tracked, some positional device must be configured to position the user's head. VR Juggler requires that each user has a head position. This may come in the form of a sensor, or it may be a simulated position device.