Installation Instructions

This page is a quick guide to get a low-cost VR environment up and running. It assumes that the hardware configuration is the recommended system as listed on the shopping list page.

Table of Contents

Step 0: Prerequisites

Step 1: Connect 3D Display to Main Computer

The 3D display needs to be connected via a digital video cable, either a DVI-to-HDMI cable connected to a DVI port on the main computer's graphics card, or a straight HDMI cable connected to an HDMI port on the main computer's graphics card. 3D TVs typically have multiple HDMI inputs, and typically one of them is designated for connections to a PC (refer to your 3D TV's manual to find out which HDMI port to use). If the main computer's graphics card only has one DVI output and one VGA output, the main display unfortunately needs to be connected via the analog VGA output. 3D does not work across an analog video link.

We recommend configuring the 3D display as a secondary display, such that the main computer's desktop shows up on a regular LCD, and VR applications show up on the 3D display. This can be achieved in several ways, but we recommend configuring the two displays as two separate X screens under the same X server. This X configuration file, which will need to be copied into /etc/X11/xorg.conf on the main computer, can serve as a template.

The template configuration file sets up two X screens: the first connected to the main display, a regular LCD, and the second one connected to the 3D display. The second screen is positioned to the right of the main screen (i.e., if the mouse cursor moves out of the main display towards the right, it will enter the 3D display), but this can be changed if the physical setup is different by replacing "RightOf" with "LeftOf" in line 7 in the template configuration file. Apart from that, the configuration file needs to be adapted in the following ways:

After copying the xorg.conf file into /etc/X11, or after any change, the main computer's X server needs to be restarted. This can be achieved by logging out and logging back in, or by pressing Ctrl+Alt+Backspace.

If everything works, the operating system's login prompt, and the user's desktop after logging in, show up on the main display, while the 3D display only shows a background image. The mouse cursor can be moved between main display and 3D display, but windows can not (this is intentional). Running glxgears as glxgears -display :0.1 will show a window with three rotating gears on the 3D display instead of the main display.

HDMI 1.4a Stereo Modes

Most newer 3D TVs expect video signals following the HDMI 1.4a standard before they switch into 3D mode. The DLP-based projection TV used as an example in this guide does not require any special setup; it simply expects a standard 1080p60 HD video signal, and Vrui takes care of the rest. If one wants to (or has to) use HDMI 1.4a stereo modes, modelines describing the precise video timings of those modes must be entered into, and selected in, the xorg.conf file. The monitor section for the 3D TV in the template X configuration file already contains those modelines, and the screen section for the 3D TV contains commented-out lines referencing those modes.

The main benefit of using HDMI 1.4a stereo modes is that newer TVs automatically switch into 3D modes when receiving them, whereas other ways of generating stereo require some interaction by the user every time the TV is turned on. The main drawback of HDMI 1.4a stereo modes is that most TVs on the market today implement only the minimum required set of modes to qualify for the "HD 3D ready" sticker, and that those modes are not very useful for VR applications. For example, while there is a full-HD 1920x1080 stereo mode, current TVs only support it at 24Hz refresh rate, which is too low for serious use.

Step 2: Configure Vrui to Render in Stereo on 3D Display

This step involves several changes to Vrui's main configuration file, Vrui.cfg in <Vrui install path>/etc/Vrui.cfg. In preparation, we recommend copying the entire "Desktop" section, and naming it after the main computer's host name (whatever is displayed when executing echo $HOSTNAME, or, if that fails, echo $HOST in a terminal). For example, section Desktop becomes section "3dtv.idav.ucdavis.edu" (including the double quotes around the host name). Throughout the rest of this document, we will use "hostname.domainname" as a placeholder for the main computer's actual host name.

Note: As of Vrui version 1.0-068, the packaged Vrui.cfg configuration file already contains a template section for 3D displays (called section "3dtv.idav.ucdavis.edu"). Editing that section might get results more quickly, but we nonetheless recommend following the steps laid out here.

Direct Vrui's Main Window To The 3D Display

The first and most important change is to tell Vrui to open its main window on the 3D display instead of the main display. Replace the copied section's "Window" section with the following:
section "hostname.domainname"
	...
	section Window
		display :0.1
		windowFullscreen true
		windowType Mono
		screenName Screen
		viewerName Viewer
		toolKillZonePos (0, 0)
	endsection
	...
endsection

The above settings are for the recommended setup, where the 3D TV is handled as a separate X screen. It is possible to run the 3D TV in so-called "TwinView" mode, where the two displays form a single seamless virtual display and windows can be moved freely between the displays. While TwinView offers some benefits, we do not recommend it because it is less reliable. Depending on how the computer is started, and whether the 3D TV is turned on or off when the user logs in, the 3D TV might or might not be recognized automatically, or it might show up in different places relative to the main display. But if an advanced user wants to employ TwinView, the "Window" section has to be modified. The "display :0.1" and "windowFullscreen true" settings have to be removed, and the following settings have to be inserted:

section "hostname.domainname"
	...
	section Window
		windowPos (<windowX>, <windowY>), (1920, 1080)
		decorate false
	endsection
	...
endsection
The <windowX> and <windowY> values define the top-left corner of the display window, and, since TwinView defines a single virtual screen, depend on the exact TwinView setup, and the size of the main display. For example, if the 3D TV's display is positioned to the right of the main display, then <windowX> must be equal to the width of the main display. If the 3D TV is positioned to the left, <windowX> must be 0. <windowY> is typically 0 when the displays are positioned side-by-side, but this might be different when the main display's vertical resolution is higher than the 3D TV's. Stereo will not work correctly if the window positions are off by even one pixel. Caveat emptor.

Enable Stereo Rendering

The next step is to tell Vrui how to generate a video signal that will show up in stereo on the 3D TV. This depends on the type of 3D TV used, and the video signal configured in Step 1.

Older DLP-based projection TVs
These TVs convert a standard 1920x1080 HD signal into stereo using a checkerboard ("quincunx") interleave pattern. To select it, the windowType Mono setting in the above configuration file fragment has to be changed to windowType InterleavedViewportStereo.
Pseudo-HDMI 1.4a stereo modes
Newer 3D TVs expect stereo signals in one of the modes defined in the HDMI 1.4a stereo standard. Several of those modes can be emulated by sending specially generated stereo frames over a standard 1920x1080 HD signal. The two most common types are top-bottom and side-by-side. In top-bottom, the original left/right frames are squished by a factor of two vertically, and placed above each other. In side-by-side, the original left/right frames are squished by a factor of two horizontally, and placed next to each other. To enable top-bottom, the windowType Mono setting in the above configuration file fragment has to be changed to:
    windowType SplitViewportStereo
    leftViewportPos (0, 540), (1920, 540) # Squish left frame by half and place it on top
    rightViewportPos (0, 0), (1920, 540) # Squish right frame by half and place it on bottom
To enable side-by-side, the equivalent new settings are:
    windowType SplitViewportStereo
    leftViewportPos (0, 0), (960, 1080) # Squish left frame by half and place it on left
    rightViewportPos (960, 0), (960, 1080) # Squish right frame by half and place it on right
Optional pseudo-HDMI 1.4a stereo modes
Some higher-end new 3D TVs additionally support interleaved stereo modes, such as quincunx or row-interleaved. Usually, all supported pseudo stereo modes are listed in the user interfaces that appears when the 3D TV is manually set to stereo mode. For active-stereo 3D TVs, checkerboard ("quincunx") is the best mode in practice. Just as with older 3D TVs, replace windowType Mono in the above configuration file fragment with windowType InterleavedViewportStereo.

Passive-stereo 3D TVs typically use row-interleaving, and some expose this stereo mode directly via row-interleaved stereo. If supported, this is the ideal mode for passive-stereo 3D TVs (the next best is top-bottom, see above). To select row-interleaved stereo, the windowType Mono setting in the above configuration file fragment has to be changed to:

    windowType InterleavedViewportStereo
    interleavePattern RRLL
The interleavePattern RRLL setting tells Vrui to interleave the left and right views row-by-row instead of the default checkerboard (which would be interleavePattern LRRL). If this pattern results in flipped stereo, replace with interleavePattern LLRR.
HDMI 1.4a frame-packing stereo modes
These are the only modes that can generate full-resolution stereo frames, but current TVs only implement 1920x1080 frame packing modes at a low refresh rate of 24 Hz. To use this mode, enable it in xorg.conf according to Step 1, and then replace the windowType Mono setting in the above configuration file fragment with:
    windowType SplitViewportStereo
    leftViewportPos (0, 1125), (1920, 1080) # Place left frame on top of right frame and "active space"
    rightViewportPos (0, 0), (1920, 1080) # Place right frame on bottom
After these changes, Vrui applications will appear on the 3D TV, and will display in stereo. Depending on the type of 3D display and the stereo mode used, stereo might have to be enabled manually on the display first. Some displays have a dedicated "3D" button on the remote; others have the setting hidden somewhere in the settings menu - refer to your display's user's manual.

A Word on Coordinate Systems and Units

Vrui uses two coordinate systems: physical and navigational coordinates. Navigational coordinates are defined and used by Vrui applications, and use application-specific units. For example, a geodesy application might use meters, and an astronomy application might use lightyears. Physical coordinates are used to describe a Vrui environment in the real world: in order to work properly, Vrui needs to know the positions, orientations, and sizes of an environment's screens, the position and viewing directions of an environment's viewers, etc. It is very important that an environment definition is internally consistent, but otherwise the position, orientation, and measurement unit of physical coordinates are completely arbitrary (with one exception: physical coordinates must be right-handed). For the rest of this guide, we assume that physical coordinates are measured in inches (1" = 0.0254m), that the origin is on the floor directly underneath the TV screen's center, that the Y axis points into the TV, and that the Z axis points up. Since physical coordinates are right-handed, this implies that the X axis points to the right when standing in front of and looking at the TV (see Figure 1). There is more detailed information about coordinate systems in Vrui's release manual, especially in "The Vrui Display Area and its Coordinate System" and "Setting up and Calibrating a Vrui VR Environment."
Figure 1: The recommended physical coordinate system used throughout this guide. The origin is on the floor, directly underneath the center of the TV screen; the X axis points to the right when looking at the TV, the Y axis points into the TV, and the Z axis points up, forming a right-handed coordinate system. The unit of measurement in physical space is 1 inch.

Configure Vrui's Display Environment

While the previous change enables stereo rendering, Vrui applications will probably not be usable yet. To get correct stereoscopic rendering, Vrui needs to know the size of the 3D display and its position in space, and the position of the viewer in the same space. Vrui's default desktop setup queries the size of the display screen from the X windows environment, which usually works well, but 3D TVs tend to lie about their own sizes, or not communicate them at all. Vrui's automatic screen size determination must therefore be disabled. Additionally, Vrui's default desktop setup contains extra features to make Vrui applications behave more like regular 3D applications when their windows are moved or resized; these features need to be disabled as well. Both these changes are made in the "Window" section:
section "hostname.domainname"
	...
	section Window
		# Disable automatic screen size determination:
		autoScreenSize false
		
		# Disable desktop-like behaviors:
		panningViewport false
		navigate false
		movePrimaryWidgets false
	endsection
endsection
Since the above settings are the default values for their respective tags, the same effect can be achieved by simply removing these tags from the "Window" section.

The second step is to measure the 3D display's size, i.e., it's exact width and height. As a first approximation it is sufficient to measure the inside size of the display's bezel; however, because most projection TVs use significant overscan, the image is typically larger than that. To get accurate immersive display, especially after installing the optical tracking system, one needs to extrapolate the actual image size by measuring a calibration grid. This will be done very precisely, using a piece of survey equipment, in Step 8. Either way, the display's width and height have to be entered into the "Screen" section:

section "hostname.domainname"
	...
	section Screen
		name Screen
		deviceMounted false
		origin (<displayX>, 0.0, <displayZ>)
		horizontalAxis (1.0, 0.0, 0.0)
		width <displayWidth>
		verticalAxis (0.0, 0.0, 1.0)
		height <displayHeight>
	endsection
	...
endsection
This will define Vrui's physical coordinate system as follows: the X axis goes from left to right parallel to the 3D display's screen, the Z axis goes upwards parallel to the screen, and the Y axis goes into the screen. The physical coordinate units are whatever units are used to measure width and height (inches, meters, etc.). We recommend setting <displayX> and <displayZ> such that the coordinate system's origin is on the floor, directly below the center of the screen; i.e., <displayX> = -<displayWidth>/2 and <displayZ> = <height of display's lower edge above the floor> (but this is completely arbitrary, and will be changed later anyways when the optical tracking system is calibrated).

After the screen's dimensions have been defined, Vrui should be told the overall size of its display space. These settings are at the beginning of the environment's main section, and should be changed as follows:

section "hostname.domainname"
	...
	inchScale <size of an inch in physical coordinates>
	meterScale <size of a meter in physical coordinates>
	displayCenter (0.0, 0.0, <height of display center>)
	displaySize <display radius>
	forwardDirection (0.0, 1.0, 0.0)
	upDirection (0.0, 0.0, 1.0)
	floorPlane (0.0, 0.0, 1.0), 0.0
	...
	newInputDevicePosition (0.0, -6.0, <height of display center>)
	...
	frontplaneDist 1.0
	backplaneDist 1000.0
	...
endsection

Configure Vrui's Viewer

Finally, Vrui needs to know the position of the viewer, i.e., the virtual camera. This is defined in the "Viewer" section:
section "hostname.domainname"
	...
	section Viewer
		name Viewer
		headTracked false
		headDeviceTransformation translate (<viewerX>, <viewerY>, <viewerZ>)
		viewDirection (0.0, 1.0, 0.0)
		monoEyePosition (0.0, 0.0, 0.0)
		leftEyePosition (-<eyeSeparation>/2, 0.0, 0.0)
		rightEyePosition (<eyeSeparation>/2, 0.0, 0.0)
		headLightEnabled true
		headLightPosition (0.0, 0.0, 0.0)
		headLightDirection (0.0, 1.0, 0.0)
		headLightColor (1.0, 1.0, 1.0)
		headLightSpotCutoff 180.0
		headLightSpotExponent 0.0
	endsection
	...
endsection

After these changes, the stereoscopic display of Vrui application should look correct. When the viewer is in the configured position, cubes should appear as cubes (not stretched boxes), and spheres should appear as spheres (not ellipsoids).

Minor Adjustments

There are still some minor configuration changes to make the display look "right." Most importantly, the font size used in menus and dialogs might be too large or too small. The font size, and the size of user interface components in general, can be changed via the following settings towards the beginning of the environment's main configuration file section:
section "hostname.domainname"
	...
	glyphSize 0.333
	...
	uiSize 0.075
	...
	uiFontTextHeight 0.15
	...
	uiSliderWidth 0.225
	...
endsection
The uiFontTextHeight setting should be adapted until the fonts look "just right." After that, the uiSize should be set to half the font height, and the uiSliderWidth setting should be set to uiSize+uiFontHeight. The glyphSize setting defines the size of input device glyphs, such as the cones used for tracked input devices, or the wireframe boxes used for virtual input devices, and should be set to a comfortable size.

Similarly, depending on the 3D screen's configured size, the default mouse-based navigation tools might be too sensitive. Their behaviors can be configured via tool-specific sections in Vrui's tool section. To adjust the default mouse navigation tool ("Mouse (Multiple Buttons)"), create a new section with that tool class' internal name, MouseNavigationTool, somewhere in the Tools section:

section "hostname.domainname"
	...
	section Tools
		...
		defaultTools DefaultTools
		
		section MouseNavigationTool
			rotateFactor <rotate>
			rotatePlaneOffset <offset>
			scaleFactor <scale>
		endsection
		...
	endsection
	...
endsection
In this section, rotateFactor is the distance by which the mouse cursor has to be moved to rotate the view by one radians. By default, this is set to 3"; a larger value will make mouse rotation less sensitive. The value to choose is a matter of personal preference, and a comfortable value should be found by experimentation. The rotatePlaneOffset setting is a secondary value influencing navigation behavior (but hard to explain). For large (72") screens, it should be set to 6" instead of the default of 3". The scaleFactor setting is analogous to rotateFactor; it is the distance by which the mouse has to be moved along the scaling direction (up/down by default) to scale the view by a factor of e (2.71...); again, larger values will make scaling less sensitive.

On many 3D displays, the hardware mouse curser is distorted or "chopped up." This can be fixed by rendering a "fake" mouse cursor. In the mouse input device adapter's section, insert the following settings:

section "hostname.domainname"
	...
	section MouseAdapter
		...
		fakeMouseCursor true
		mouseCursorSize (<width>, <height>, 0.0)
		...
	endsection
endsection
The mouseCursorSize setting is optional, and should be omitted initially. It can later be added to adjust the size of the cursor if it appears too large or too small. The cursor's width and height are defined in physical coordinate units.

Finally, the size of Vrui's "tool kill zone" (the red box in the lower-left hand corner of the screen) should be adjusted such that it is big enough to be found easily. The size is configured in the environment's tool section:

section "hostname.domainname"
	...
	section Tools
		...
		killZoneSize (<width>, 0.1, <height>)
		...
	endsection
	...
endsection
The width and height of the kill zone are given in physical coordinates, i.e., inches in the default setup. The kill zone should be comfortably big; for a 72" 3D TV, we recommend a width of 6" and a height of 3".

By default, the tool kill zone is placed in the lower-left hand corner of the screen. For right-handed users, it might be more comfortable to move it to the lower-right hand corner. To do so, edit the kill zone's position in the environment's window section:

section "hostname.domainname"
	...
	section Window
		...
		toolKillZonePos (<posX>, <posY>)
		...
	endsection
	...
endsection
The kill zone positions are relative to the screen. a <posX> of 0.0 corresponds to the left edge, 1.0 corresponds to the right edge. Analogously, a <posY> of 0.0 corresponds to the bottom edge, and 1.0 corresponds to the top edge. To move the kill zone to the lower-right hand corner, set its position to (1, 0).

Step 3: Install Optical Tracking System

The NaturalPoint OptiTrack tracking system is responsible for determining the position of the viewer's eyes in 3D space, which is essential for proper "holographic" display. It is additionally used to determine the position and orientation of hand-held input devices with which users interact with 3D applications. Unfortunately, OptiTrack is a Windows-only program, and thus requires a separate Windows computer to run (we have not managed to install it under wine, or inside a virtual machine running Windows). We recommend connecting that computer to the same network as the main computer running the 3D display, such that the main computer can receive tracking data from the tracking computer via the network. For this, Vrui needs to be told the host name of the tracking computer, which is entered into Vrui's configuration file in step 6.

An important decision is where to place the tracking cameras with respect to the 3D TV. An alternative blueprint for low-cost VR environments, the IQ-station, places the cameras on the edge or around the TV screen. Due to the small field of view of the cameras, this requires six cameras to create a sufficient tracking space. We recommend to mount the cameras on the ceiling or a wall above the 3D TV, which will lead to a large tracking volume and high-quality tracking using only three cameras (a $1500 savings). One recommended OptiTrack camera placement is shown in Figure 2; an alternative placement that works with lower ceilings, and can sometimes yield better tracking results, is shown in Figure 3.
Figure 2: One recommended camera placement for a three-camera NaturalPoint OptiTrack optical tracking system. The shown TV's diagonal is 72", and each camera's horizontal field of view is 45°. The vertical field of view of the cameras should not include the screen itself to reduce ghost tracking markers due to reflection, as shown in the side view.
Figure 3: Alternative camera placement for a three-camera NaturalPoint OptiTrack optical tracking system for rooms with lower ceilings. The left and right cameras are pushed outwards by about 1-2 feet to increase the width of the tracking volume, and cover the entire TV screen. The extended stereo baseline yields more stable tracking, but the increased displacement between the cameras makes it harder to construct reliable tracking markers. The shown flat screen TV's diagonal is 70", and each camera's horizontal field of view is 45°. As in Figure 2, the vertical field of view of the cameras exactly grazes the screen's surface to prevent ghost tracking markers.
When aiming the tracking cameras, it is important that the TV screen itself is not inside the cameras' field of view. Due to the high reflectivity of typical screen materials, the cameras will pick up the reflections of the tracking markers in the screen, which leads to "ghost" tracking markers and instability. We recommend to carefully align the cameras such that their fields of view exactly graze the screen. An easy way to achieve that is to temporarily glue six tracking markers to the four corners of the TV and the midpoints of the upper and lower edges, and then aim the cameras such that each camera sees the bottom row of markers exactly along one of the edges of its image, such that the markers are cut approximately in half. In the ideal case, where the cameras' focal points are exactly above the screen in the screen's plane, all six markers will appear in a single line along an image edge.

Step 4: Calibrate Optical Tracking System Internally

This process is described in detail in OptiTrack's user's manual. As a rule, the convergence results reported at the end of the calibration procedure should be "great" or "excellent" for all cameras. Lesser results will work, but result in jittery and inaccurate tracking data. In the last calibration step, OptiTrack's global coordinate system is defined by placing a ground triangle. We recommend placing the triangle such that OptiTrack's coordinate system roughly matches Vrui's coordinate system, which will simplify Vrui calibration later. To do so, the central marker on OptiTrack's ground triangle should be placed on the floor, directly underneath the center of the 3D display, i.e., coinciding with the origin of Vrui's coordinate system. The ground triangle's X axis should point to the right, parallel to the 3D display's screen; as a result, the triangle's Z axis will point away from the screen.

Step 5: Create Tracking Antlers for Head Tracker and Input Devices

Each tracked device (stereo glasses, Wii controller) needs a rigid constellation of at least three tracking markers to be tracked by OptiTrack's rigid body toolkit in position and orientation. It is important to create constellations that are asymmetric, such that the software can deduce the orientation of each body unambiguously, and distinguishable, so that the software can tell the different tracked devices apart. Refer to the Pictures page to see our head tracker and wand tracker.

OptiTrack allows assigning arbitrary names to defined rigid bodies, but we recommend naming the rigid body attached to the tracked 3D glasses "Head," and the one attached to the Wiimote "Wand." After all rigid bodies have been defined, OptiTrack's rigid body toolkit can be used to visually test the tracking quality. As all tracked devices are moved around in the tracking space, OptiTrack should be able to follow them, and tell them apart. If tracking fails, or OptiTrack has trouble telling the rigid bodies apart, it might be necessary to change the physical layout of the tracking antlers.

After initial setup, the following steps have to be performed each time OptiTrack's rigid body toolkit is started, before Vrui will be able to receive tracking data:

  1. Load a calibration file, by clicking the button in the top-left corner of the window.
  2. Load rigid body definitions, by selecting File->Load Rigid Body Definitions from the program's main menu.
  3. Expand the "Streaming" tab at the right edge of the window, and check the "Stream frame data" button in the "VRPN" section.
The new OptiTrack Tracking Tools software has a simplified start-up sequence. It is only necessary to load the previously saved project file, which will in turn load the calibration data, the rigid body definitions, and enable streaming.

Step 6: Configure Vrui VR Device Driver to Receive Tracking Data

Vrui receives tracking data from OptiTrack's rigid body toolkit, and button events from the Wiimote, via VRDeviceDaemon, its stand-alone VR device driver daemon. A diagram of this setup is shown in Figure 4. VRDeviceDaemon is configured via its own configuration file, VRDevices.cfg, which is stored in the same directory as Vrui's main configuration file, Vrui.cfg. The VRDevices.cfg file packaged with the Vrui source distribution contains a section "3dtv.idav.ucdavis.edu" which can be used as a template. We recommend copying the entire section, and naming it after the main computer's host name (whatever is displayed when executing echo $HOSTNAME, or, if that fails, echo $HOST in a terminal). For example, section "3dtv.idav.ucdavis.edu" becomes section "hostname.domainname" (including the double quotes around the host name).

The template section contains comments indicating which settings have to be changed:

Figure 4: Diagram showing the overall structure of the device and driver setup. The Windows PC is connected to the OptiTrack cameras via USB, and is running the OptiTrack driver software. The Linux PC is connected to the Wiimote, and is running Vrui's own device driver (VRDeviceDaemon) and any Vrui applications. VRDeviceDaemon talks to OptiTrack's driver via the VRPN protocol, and to the Wiimote via Bluetooth. Vrui applications, and the DeviceTest utility, talk to VRDeviceDaemon via its own internal protocol.

Start Vrui VR Device Driver

Before Vrui applications can receive tracking data, the stand-alone Vrui device driver, VRDeviceDaemon, must be started. VRDeviceDaemon can be run as a system-level service (or "daemon"), but in this particular setup, it is best run as an on-demand server. The primary reason is that the Wiimote must stay connected to the driver during its entire lifetime, and since the Wiimote connects via Bluetooth, this depletes the Wiimote's batteries rather quickly. We therefore recommend to only start VRDeviceDaemon when a user begins working with the low-cost system, and to shut it down afterwards. (And we recommend using rechargeable batteries for the Wiimote.)

After VRDevices.cfg has been changed according to the preceding section, it is possible to start VRDeviceDaemon from a terminal window, without any command line arguments. Figure 5 shows a typical start-up sequence. Upon startup, VRDeviceDaemon will first try to connect to the OptiTrack rigid body toolkit, print some status information, and then try to connect to the Wiimote. At that point it will prompt the user to press buttons 1 and 2 on the Wiimote simultaneously to put the device into discovery mode. When the user presses these buttons (see important note below), the blue LEDs at the base of the Wiimote will start flashing. The number of flashing LEDs indicates the charge level of the battery (4 LEDs: full, 1 LED: almost empty). VRDeviceDaemon will try to connect to the Wiimote for 30 seconds after the prompt appears; if it cannot connect in that period, it will print an error message and terminate. If it connects successfully, VRDeviceDaemon will print the number of served trackers (should match the number of configured senders, e.g., 2 in the default configuration) and the number of buttons and valuators, which should be 13 and 2, respectively, for a Wiimote with optional Nunchuck attachment. Finally, it will print "Waiting for client connection" and wait for client connections.

Important Note: Pressing buttons 1+2 simultaneously no longer works with newer Wiimote models, particularly with the new Wiimote Plus that has an integrated MotionPlus extension. On these models, pressing 1+2 will put the Wiimote into temporary discovery mode, which requires using an authenticated Bluetooth protocol and does not work with VRDeviceDaemon. The new connection procedure is to press the red "sync" button hidden underneath the battery cover only for the first time a particular Wiimote is connected to VRDeviceDaemon, and press any single button (except the 1+2 combo) every time afterwards. This new procedure, which does not work with older Wiimotes, will bypass discovery mode and directly connect to the last Bluetooth host with which the Wiimote was connected, which takes much less time. In case the Wiimote is reset by pressing the 1+2 combo, of by being connected to a different Bluetooth host, the sync button has to be used again the next time it is connected to VRDeviceDaemon.
> VRDeviceDaemon

VRDeviceDaemon: Reading configuration file
VRDeviceDaemon: Initializing device manager

VRDeviceManager: Loading device VRPN1 of type VRPNClient
VRPNConnection: Checking server version number... done
VRPNConnection: Server version is vrpn: ver. 07.15
VRPNClient: Initializing senders... done

VRDeviceManager: Loading device Wiimote1 of type WiimoteTracker
WiimoteTracker: Connecting to bluetooth device 00:1F:C5:21:CA:46.
WiimoteTracker: Please press buttons 1 and 2 to initiate connection... done
WiimoteTracker: Connected wiimote's battery level is 58%

VRDeviceManager: Managing 2 trackers, 13 buttons, 2 valuators
VRDeviceDaemon: Initializing device server
VRDeviceServer: Waiting for client connection
Figure 5: Typical VRDeviceDaemon start-up sequence when started on-demand from a terminal window. When the "Please press buttons 1 and 2 to initiate connection..." prompt appears, the user has 30 seconds to do so or the driver will abort with an error message (but see the important note above). After the "Waiting for client connection" message appears, the driver is ready to serve tracking data to Vrui applications.

Test Vrui VR Device Driver

Vrui contains a text-based test program for the VR device daemon, DeviceTest. It connects to a running VRDeviceDaemon and prints real-time updates of selected tracker positions and/or orientations, or button and/or valuator states.

Command Line

DeviceTest <server host name>:<server port> [-t <tracker index>] [-alltrackers] [-p | -o | -f | -v] [-b]

Arguments

<server host name>:<server port>
The host name or IP address and listening port of the VR device daemon to which to connect.
-t <tracker index>
The index of the tracker whose state to print. If omitted, this defaults to 0, the first tracker.
-alltrackers
If the printing mode is to print positions only, print the positions of all trackers.
-p | -o | -f | -v
Selects which device state(s) to print.
-p
Print tracker position only.
-o
Print tracker position, and orientation as a rotation around an axis.
-f
Print tracker position, and orientation as a local frame of three orthogonal axes.
-v
Print states of all valuators instead of tracker positions or orientations.
If omitted, this defaults to printing the selected tracker's position only.
-b
Print states of all buttons (X: pressed) along with other state.
If everything is working properly, DeviceTest will continuously print device states as they are delivered from the VR device daemon, until it is interrupted by pressing any key. When exiting, it will print the total number of state updates received, and the average update rate in updates/s.

It is important to ensure that the tracking results reported by VRDeviceTest roughly match the expected behavior. I.e., when moving a tracked device to the right, the X coordinate of its position should increase; when moving it up, the Z coordinate should increase. When a device is moved close to the center of the screen, its displayed position should roughly match the screen center as configured in Vrui.cfg.

Step 7: Configure Vrui to Receive Tracking Data

Vrui's desktop configuration receives input device data only from a mouse and keyboard. To add input devices provided by Vrui's device driver, VRDeviceDaemon, several changes need to be made to Vrui.cfg. In the section "hostname.domainname" created in step 2, find
section "hostname.domainname"
	...
	inputDeviceAdapterNames (MouseAdapter)
	...
endsection
and replace it with
section "hostname.domainname"
	...
	inputDeviceAdapterNames (MouseAdapter, DeviceDaemonAdapter)
	...
endsection
Then, find section MouseAdapter, and, after it, insert a new section DeviceDaemonAdapter:
section "hostname.domainname"
	...
	section MouseAdapter
		...
	endsection
	
	section DeviceDaemonAdapter
		inputDeviceAdapterType DeviceDaemon
		serverName "hostname.domainname"
		serverPort 8555
		inputDeviceNames (Head, Wand)
		
		section Head
			name Head
			trackType 6D
			trackerIndex 0
		endsection
		
		section Wand
			name Wand
			trackType 6D
			trackerIndex 1
			numButtons 13
			buttonIndexBase 0
			numValuators 2
			valuatorIndexBase 0
			deviceGlyphType Cone
		endsection
	endsection
	...
endsection

This change will create two new 3D input devices, one ("Head") representing the tracked 3D glasses, and the other ("Wand") representing the Wiimote, including its buttons and the (optional) joystick in the Nunchuck extension. The next steps are to tell Vrui to use the Head device for head tracking, and to attach some default interaction tools to the Wand device.

Enable Head Tracked Rendering

This step is simple: Vrui's viewer (the virtual camera) needs to be told that it is to use the 3D position and orientation of the Head device instead of the fixed position and orientation configured in Step 2. Find the environment's Viewer section:
section "hostname.domainname"
	...
	section Viewer
		...
		headTracked false
		...
	endsection
	...
endsection
and replace the headTracked setting with
section "hostname.domainname"
	...
	section Viewer
		...
		headTracked true
		headDevice <head device name>
		...
	endsection
	...
endsection
where <head device name> is the name of the input device attached to the tracked 3D glasses as configured above, i.e., Head in the recommended configuration.

Add Additional Tool Classes and Set Up Default Tools

Vrui contains several interaction tools that are only useful in immersive environments with tracked input devices, and are therefore not part of the default tool set for desktop systems. For optimal usability, these tools should be added to the toolClassNames setting in the Tools section:
section "hostname.domainname"
	...
	section Tools
		...
		toolClassNames (..., \
		                WalkSurfaceNavigationTool, \
		                ScaleNavigationTool, \
		                ValuatorScalingNavigationTool, \
		                WandNavigationTool, \
		                SixDofWithScaleNavigationTool, \
		                TwoHandedNavigationTool, \
		                MultiDeviceNavigationTool, \
		                FlyNavigationTool, \
		                ValuatorFlyNavigationTool, \
		                ValuatorTurnNavigationTool, \
		                ValuatorFlyTurnNavigationTool, \
		                WalkNavigationTool, \
		                ForceJumpNavigationTool)
		...
	endsection
	...
endsection
Vrui allows to dynamically attach user interation tools to input devices, but it is useful to have a set of default tools that is available as soon as a Vrui application starts. Default tool assignments are listed as individual sections underneath the DefaultTools section inside an environment's Tools section. Each section defines one tool, and sections are processed in the order in which they are listed. Find the DefaultTools section
section "hostname.domainname"
	...
	section Tools
		...
		section DefaultTools
			...
		endsection
		...
	endsection
	...
endsection
and insert three new sections after section MenuTool as follows:
section "hostname.domainname"
	...
	section Tools
		...
		section DefaultTools
			...
			section MenuTool
				...
			endsection
			
			section WandNavTool
				toolClass WandNavigationTool
				bindings ((<wand device name>, Button3, Button8))
			endsection
			
			section WandGUITool
				toolClass WidgetTool
				bindings ((<wand device name>, Button8))
			endsection
			
			section WandMenuTool
				toolClass RayMenuTool
				bindings ((<wand device name>, Button8))
			endsection
		endsection
		...
	endsection
	...
endsection
where <wand device name> is the name of the wand device as configured in the DeviceDaemonAdapter section.

After these changes, Vrui should render head-tracked stereo, i.e., the image on the screen should change as the tracked 3D glasses are moved in the tracking space, and it should display a grey cone roughly following the motions of the Wiimote. When pressing the arrow down button on the Wiimote, a Vrui application's main menu should be displayed, and when pressing the "A" button, the 3D model displayed by an application can be moved in position and orientation. Pressing first the "A" button, and then the arrow down button while holding the "A" button allows to increase or decrease the size of the displayed model by moving the Wiimote forward or backwards.

Enable Screen Saver

When working with an immersive display, the physical screen becomes virtually invisible, because objects can appear both in front of it and behind it. This often leads to a user trying to touch an object that is behind the screen, and hitting the screen in the process. To minimize the chance of damaging the screen, Vrui offers a literal screen saver: when any input device comes too close to any screen, a green grid will appear on that screen. These grids will show the 3D position of any physical screen, and allow users to avoid hitting it. Screen savers need to be enabled in two places: first, a "danger sphere" needs to be defined around each input device to be monitored (this can include head trackers); and second, screen saving needs to be enabled in any window rendering to any screen to be protected.

The first step happens in the root section. After the screenNames setting, insert a screenProtectors setting as follows:

section "hostname.domainname"
	...
	screenNames (...)
	screenProtectors ( (<head device name>, (0.0, 0.0, 0.0), 24.0), \
	                   (<wand device name>, (0.0, 0.0, 0.0), 6.0) )
	...
endsection
Each item in the screenProtectors list defines a sphere around an input device. The input device is identified by its name (such as "Head" or "Wand"), and the sphere is defined by its center point in the device's local coordinate system, and its radius in physical coordinate units. The settings here, assuming Vrui uses inches as physical coordinate units, define a sphere of radius 24 inches around the head device's origin, and a sphere of radius 6 inches around the wand device's origin. For 3D TVs, where users typically sit very close to the screen, the wand sphere's radius can be reduced, say to 4 inches. This is a matter of taste and experimentation. The radius needs to be large enough such that the screen saver grid can be displayed early enough to prevent the user from hitting the screen with the wand device, based on the user's typical reaction time and maximum speed of moving the wand.

The second step happens in the window section. The protectScreens setting needs to be set to true if it exists, or needs to be removed (the setting defaults to true):

section "hostname.domainname"
	...
	section Window
		...
		protectScreens true
		...
	endsection
	...
endsection

Step 8: Calibrate 3D Display and Optical Tracking System

At this point, the 3D display should basically be working, but it will not be well-calibrated. Most importantly, stereo might be painful to look at - when holding the tracked 3D glasses level, the two images on the display might show a vertical displacement additional to the expected horizontal displacement. The reason for this is that OptiTrack assigns a "random" local coordinate system to a new rigid body as it is defined, meaning that Vrui might think the glasses are held at an angle when they are in fact level. For the same reason, the menu selection ray that is supposed to project straight forward from the Wiimote when the "Home" button is pressed might project in any other direction instead. Additionally, there might be positional mismatches between the Wiimote, and the grey cone Vrui uses to indicate its position. Ideally, the two should exactly coincide. Both these issues need to be resolved by properly calibrating the 3D display with respect to the OptiTrack system, and defining proper local coordinate frames to all tracked rigid bodies.

Calibrate Screen Size and Align Global Coordinate Systems

The first calibration step is to accurately measure the size of the 3D display's screen, and align the coordinate system used by OptiTrack with the coordinate system used by Vrui. The result of this step is a globally calibrated system, where 3D objects appear somewhat solid as the viewer moves his/her head around, and the cone indicating the wand's position generally follows the motion of the wand device. Stereo might still be "off," and there might be an offset in the wand, or the wand's cone might point in the wrong direction -- these problems will be fixed in the second calibration step.

Unfortunately, performing this first calibration properly requires a 3D measuring device, which can accurately measure the 3D positions of arbitrary points in space, such as a geodetic theodolite with a laser range finder (a so-called "Total Station"). If such a device is available, Vrui contains three calibration utilities that more or less automate the process. A user simply has to measure a set of regularly placed points on the 3D display's screen (to measure its size and position in space), and then measure the positions of a set of tracking markers which are captured at the same time by the OptiTrack system.

Run MeasureEnvironment

The MeasureEnvironment utility is used to measure 3D points on the floor around the 3D TV, points on the 3D TV's screen, and the position of tracking markers in the tracked space in front of the 3D TV. To simplify the process, it connects directly to a Leica TCR407 power Total Station (other models may or may not be supported depending on their serial port protocols), and can also directly connect to an OptiTrack server using the Natural Point streaming protocol.

First, the XBackground utility is run to show a regular grid on the 3D TV:

XBackground -display :0.1 -type 2 -size 300
The argument after -display indicates on which screen to show the calibration grid. In the recommended setup, the 3D TV corresponds to display :0.1. The argument after -size specifies the grid spacing in pixels. 300 is a good compromise between effort and precision for 3D TVs running at a resolution of 1920x1080 pixels. Important note: The 3D TV needs to be switched out of 3D mode when XBackground is run, to avoid a distortion of the grid. When properly set up, all grid cells should appear exactly square.

Then, MeasureEnvironment itself is run:

MeasureEnvironment -t <serial port name> -npc <OptiTrack server name> -rootSection Desktop
<serial port name> is the name of the serial port connected to the Total Station, e.g., /dev/ttyUSB0, and <OptiTrack server name> is the host name or IP address of the Windows computer running the OptiTrack software. As built, the Natural Point client only works with the new OptiTrack (Tracking Tools) software. Connecting it to the older (Rigid Body Toolkit) software requires one small change in the source code. The -rootSection Desktop setting tells Vrui to run the application in desktop mode on the computer's main display instead of the 3D TV. The recommended measurement process is described in detail on the utility's manual page. MeasureEnvironment will save all recorded points upon exit, but it is recommended to save the current point set at multiple points in the procedure, and at least after completing each stage, to minimize data loss.

Run ScreenCalibrator

After the three environment measurement steps (floor, screen, balls) have been completed, the ScreenCalibrator utility is used to calculate the two sets of global calibration parameters. This is a non-interactive utility, but still has a graphical user interface to visually assess the quality of the global calibration. ScreenCalibrator is run thus:
ScreenCalibrator -screenSize 1920 1080 -squareSize 300 -metersToInches MeasuredPoints.csv TrackingPoints.csv -rootSection Desktop
The -screenSize argument specifies the size of the 3D TV screen in pixels. 1920 1080 is the standard resolution of 3D TVs. The -squareSize argument specifies the size of the calibration grid in pixels; this value must match the same value given on XBackground's command line. -metersToInches instructs ScreenCalibrator to automatically convert all measurements from meters, which is the default unit of measurement both for the Total Station and OptiTrack, to inches, which is Vrui's physical measurement unit used in this guide. If a different measurement unit was chosen, the -metersToInches argument needs to be replaced with -unitScale <scale>, where <scale> is the conversion factor from meters to the chosen unit. If Vrui's unit is meters, the argument is -unitScale 1.0, if it is centimeters, it is unitScale 100.0, if it is inches, it is -unitScale 39.37007874, or simply -metersToInches. MeasuredPoints.csv is the default name of the file containing Total Station measurements, and TrackingPoints.csv is the default name of the file containing OptiTrack measurements, when using the NaturalPoint client. -rootSection Desktop again instructs Vrui to run the application on the main display in desktop mode.

When ScreenCalibrator is started, it immediately calculates the screen transformation, i.e., the position, orientation, and exact size of the 3D TV, and the tracking transformation, i.e., the conversion from OptiTrack coordinates to Vrui coordinates. ScreenCalibrator's display will show the collected measurement points (floor points in red, screen points in green, ball points in purple and OptiTrack points in yellow). It will show the best-fitting rectangular screen in green, and the best-fitting projective (keystone-corrected) screen in blue. For flat-screen 3D TVs, the green and blue quadrilaterals will be almost exactly the same; for projection-based TVs, there might be significant differences due to internal keystone distortion. The configuration settings returned by ScreenCalibrator will undo that distortion as much as possible. If there is a significant difference between the green and blue quadrilaterals for a flat-screen TV, something probably went wrong during measurement. Finally, ScreenCalibrator will show the alignment quality of the optical tracking system by drawing yellow/purple lines connecting each pair of associated ball and tracking points. In a good configuration, these lines should be invisible at a scale where the entire screen is visible, because the aligned 3D coordinates will match almost exactly. Lines will only show up when zooming into individual point pairs. If there are visible alignment lines, both OptiTrack's intrinsic calibration procedure and the environment measurement steps should be repeated.

The result of running ScreenCalibrator are two sets of Vrui settings. The first set describes the exact size and position of the 3D display's screen, including keystone correction, and needs to be pasted into Vrui.cfg, in the environment's Screen section. The second set is a global transformation from OptiTrack space to Vrui space, and needs to be pasted into VRDevices.cfg, in the environment's Calibrator section. Both sets of settings assume the "standard" 3D TV setup, where the screen is centered above the origin, and more or less aligned to the (x, z) plane, with the y axis pointing into the screen. If Vrui's environment was set up using a different coordinate system, the values returned by ScreenCalibrator will not work directly and need to be transformed manually.

Configure Screen

The screen-related output of the ScreenCalibrator utility follows the heading "Configuration settings for screen:" and looks like the following (these are the results from measuring our 72" Samsung 3D display):
origin (-31.638, 0.151329, 29.0991)
horizontalAxis (1, -0.000486263, -0.000351728)
width 63.277
verticalAxis (0.00034805, -0.00754295, 0.999971)
height 35.7028
offAxis true
homography ( ( 31.7043, 0.00439951, -0.000280895 ), \
             ( 0.16926, 18.0794, 0.00544898 ), \
             ( 31.6448, 17.8926, 1 ) )
These settings replace the settings of the same names in the environment's Screen section in Vrui.cfg, i.e., the Screen section becomes:
section "hostname.domainname"
	...
	section Screen
		name Screen
		deviceMounted false
		origin (-31.638, 0.151329, 29.0991)
		horizontalAxis (1, -0.000486263, -0.000351728)
		width 63.277
		verticalAxis (0.00034805, -0.00754295, 0.999971)
		height 35.7028
		offAxis true
		homography ( ( 31.7043, 0.00439951, -0.000280895 ), \
		             ( 0.16926, 18.0794, 0.00544898 ), \
		             ( 31.6448, 17.8926, 1 ) )
	endsection
	...
endsection
The homography setting defines the keystone correction factors appropriate for the used 3D TV. These are from a 72" DLP projection TV with noticeable distortion; for modern flat screen (LED/LCD/Plasma) TVs, the homography matrix should be very close to a scaling and translation matrix.

Configure Global Coordinate Transformation

The transformation-related output of the ScreenCalibrator utility follows the heading "Configuration settings for tracking calibrator:" and looks like the following (these are the results from our OptiTrack calibration):
transformation translate (-0.122542, -9.505, 1.65272) \
               * scale 39.3701 \
               * rotate (0.00461419, -0.696002, -0.718025), 179.689
This setting replaces the setting of the same name in the environment's Calibrator section in VRDevices.cfg, i.e., the Calibrator section becomes:
section "hostname.domainname"
	...
	section DeviceManager
		...
		section VRPN1
			...
			section Calibrator
				transformation translate (-0.122542, -9.505, 1.65272) \
				               * scale 39.3701 \
				               * rotate (0.00461419, -0.696002, -0.718025), 179.689
			endsection
			...
		endsection
		...
	endsection
	...
endsection

Align Coordinate Frames of Tracked Rigid Bodies

The final calibration problem is that when the tracked rigid bodies, specifically the head and wand trackers, are defined within OptiTrack, OptiTrack does not know what local coordinate system should be assigned to them, so it assigns a "random" one. For example, the cone representing the wand in the 3D display might not be at the desired location, and might point in a random direction, not the wand's intended pointing direction. To fix this, one needs to read each rigid body definition from inside OptiTrack, and calculate a transformation from the assigned coordinate system to the desired one. For example, a good local coordinate system for the head tracker would have the X axis pointing to the right and the Z axis pointing straight up. This will make it easier to define eye positions for good stereo. A good wand coordinate system would have the X axis pointing right, and the Y axis pointing directly forward.

Vrui contains a calibration application, AlignTrackingMarkers, to create such local coordinate transformations. When using an old version of the OptiTrack software (the "rigid body toolkit"), it reads the rigid body definition file created by OptiTrack (file extension .rdef), and allows the user to visually adjust the local coordinate systems as desired. With the newer "tracking tools" version of the OptiTrack software, AlignTrackingMarkers connects directly to the running OptiTrack software, and then offers the same visual interface. The AlignTrackingMarkers application is described in detail on the Calibration Utilities page. Because the application works best in desktop mode, it should be run with the -rootSection Desktop additional command line option. For old (rigid body toolkit) OptiTrack:

AlignTrackingMarkers -inches <OptiTrack .rdef file name> <rigid body name> -rootSection Desktop
For new (tracking tools) OptiTrack:
AlignTrackingMarkers -inches -npc <OptiTrack server name> <rigid body ID> -rootSection Desktop
Both command lines assume that Vrui has been configured to use inches as physical measurement units. If that is not the case, refer to the Calibration Utilities page. The <rigid body name> in the first line is the alphanumeric name assigned to the rigid body in OptiTrack (such as "Head" or "Wand"). The <OptiTrack server name> in the second line is the host name or IP address of the Windows computer running the OptiTrack software, and the <rigid body ID> is the numerical ID assigned to the rigid body inside OptiTrack. For the direct connection to work, UDP ports 1510 and 1511 must be opened on the Linux computer's firewall, and the two computers must be able to send multicast packets to each other. In practice, this means they need to be connected to the same network switch.

Finally, the Tracking Tools software won't stream rigid body model data to clients unless it can see the rigid body. This means that, before starting AlignTrackingMarkers for a rigid body, that body must be placed in the field-of-view of the tracking cameras, ideally on a stable surface.

Recommended Coordinate System Layout for Tracked Bodies

In principle, Vrui can handle arbitrary coordinate systems for its tracked bodies. However, the following "canonical" layout will work most easily because it matches all the default configuration values in Vrui. For head-tracked glasses, the X axis should be going from the left to the right, parallel to an imaginary line connecting the user's eyes. The Z axis should point straight up when the user holds her head level, and the right-handedness of the coordinate system then implies that the Y axis points straight forward. The origin of the head tracker coordinate system should be in a position that can easily be related to the viewer's eyes, such as centered above the glasses' nose piece.

For hand-held input devices such as the Wiimote, the origin of the coordinate system defines the "hot spot" for interactions. It should therefore be in an obvious and easily-observed position. Most users will use the physical input device itself to judge where they are grabbing virtual space, without specifically looking for the virtual cone representing the device's position in virtual space. For example, in a tracking antler arrangement like the one shown in Figure 6, the origin should be in the center of the most forward-pointing reflective marker. The Y axis is the input device's major pointing direction, i.e., menu selection and GUI interaction rays will by default point along the Y axis. Therefore, the axis should point straight forward from the device. The X  axis should point to the right, and the Z axis will then point straight up.
Figure 6: "Canonical" layout of local coordinate systems for head-tracked glasses and tracked Wiimote. The glasses are drawn from the front, which is why the X axis is going to the left (when put on, the X axis points to the right). The coordinate system origin on the Wiimote is chosen such that it is easiest to interact with virtual objects in the environment.

Configure Tracker Coordinate Systems

Upon exiting, AlignTrackingMarkers prints a result transformation, which needs to be pasted into VRDevices.cfg. The output will look similar to:
Final transformation: translate (-0.096585, -1.048017, 0.367297) * rotate (-0.179350, -0.866056, -0.466668), 140.707679
To apply it, open VRDevices.cfg and find the environment's main section:
section "hostname.domainname"
	...
	section DeviceManager
		...
		section VRPN1
			...
			# Enter calibration transformations for the rigid bodies here
			trackerPostTransformation0 translate (0.0, 0.0, 0.0) \
			                           * rotate (1.0, 0.0, 0.0), 0.0
			trackerPostTransformation1 translate (0.0, 0.0, 0.0) \
			                           * rotate (1.0, 0.0, 0.0), 0.0
			...
		endsection
		...
	endsection
	...
endsection
Then replace the appropriate trackerPostTransformation, i.e., trackerPostTransformation0 for the tracked 3D glasses and trackerPostTransformation1 for the Wiimote, with the final transformation (the output after "Final transformation:"). Assuming that AlignTrackingMarkers above was run for the Head rigid body, the result would be:
section "hostname.domainname"
	...
	section DeviceManager
		...
		section VRPN1
			...
			# Enter calibration transformations for the rigid bodies here
			trackerPostTransformation0 translate (-0.096585, -1.048017, 0.367297) \
			                           * rotate (-0.179350, -0.866056, -0.466668), 140.707679
			trackerPostTransformation1 translate (0.0, 0.0, 0.0) \
			                           * rotate (1.0, 0.0, 0.0), 0.0
			...
		endsection
		...
	endsection
	...
endsection
(Backslashes can be used in configuration files to break long values over multiple lines.)

Fine-tune Viewer's Eye Positions

After all tracked rigid bodies' coordinate system have been aligned, the last calibration step is to precisely specify the viewer's eye positions in the head tracker's local coordinate system. The default Viewer configuration has the left eye at (-1.25, 0.0, 0.0) and the right eye at (1.25, 0.0, 0.0). This would only be correct if the head tracker's local coordinate origin were exactly halfway between the user's eyes. Since it is typically offset to the front and upwards, the correct displacement values need to be entered into Vrui's configuration file. This step usually requires some assistance, and some iteration. The intended viewer puts on the head-tracked glasses like they would be worn in normal use, and asks a second person to estimate the viewer's eye positions relative to the head tracker's origin using a ruler. The measured or estimated values are entered in four places into the environment's Viewer section:
section "hostname.domainname"
	...
	section Viewer
		...
		monoEyePosition (<monoX>, <monoY>, <monoZ>)
		...
		leftEyePosition (<leftX>, <leftY>, <leftZ>)
		rightEyePosition (<rightX>, <rightY>, <rightZ>)
		...
		headLightPosition (<monoX>, <monoY>, <monoZ>)
		...
	endsection
	...
endsection
(<leftX>, <leftY>, <leftZ>) and (<rightX>, <rightY>, <rightZ>) are the 3D positions of the viewer's left and right eyes, respectively, in the head tracker's local coordinate system, i.e., relative to its origin and along its axes. In the canonical head tracker coordinate system layout, <leftX> is typically equal to -<rightX> and <leftY> = <rightY> and <leftZ> = <rightZ>. The monoEyePosition and headLightPosition tags should be set to the midpoints of the line connecting the left and right eye positions. In the canonical head tracker coordinate system layout, this typically means <monoX> = 0 and <monoY> = <leftY> = <rightY> and <monoZ> = <leftZ> = <rightZ>.

As it is typically difficult to measure a viewer's eye positions precisely, it is usually necessary to judge the alignment result visually and adjust the positions until the alignment is sufficiently good. Vrui contains a utility for this purpose, VruiCalibrator in the ExamplePrograms subdirectory. On startup, VruiCalibrator displays a wireframe cube in the center of the display, and a coordinate frame for each tracked device, drawn as a red line parallel to the device's X axis, a green line parallel to the Y axis, and a blue line parallel to the Z axis. The intersection of the three lines indicates the coordinate system's origin. The process is to put on the head-tracked glasses, and hold a tracked device in front of the display. Ideally, the three lines' intersection should always exactly coincide with the device's hot spot, e.g., with the most forward-facing reflective ball, no matter where the device is moved and how it is oriented.

Step 9: Success! Run Fully-Immersive VR Applications

Congratulations! At this point, the low-cost VR system is fully set up and calibrated. It is now possible to run any Vrui application on the 3D TV using head-tracking and the Wiimote as a 6-DOF tracked input device. See Figure 7 for a video showing 3D Visualizer on our 72" projector-based 3D TV.
Figure 7: Video showing 3D Visualizer on our 72" projector-based 3D TV to visualize and analyze an X-ray computed tomogram of a patient's head. Notice how the grey cone indicating the Wiimote's position exactly follows the physical Wiimote, or, more precisely, the top sphere in its tracking antler, which was configured as its center point. The slight delay between motions of the physical Wiimote and its cone is due to the low performance of the (cheap) Windows computer running the tracking software. Instead of the theoretical maximum of 100 samples per second, it can only achieve around 40 samples/second.