OpenVR Tracking Proxy

Published on July 17, 2025

I had a major breakthrough with the software for my VR treadmill projects. Open VR has one reference to a treadmill device type, but unfortunately it seems that a native interface for treadmills was never implemented.

~~~ openvr_driver.h ~~~

/** Describes what specific role associated with a tracked device */
enum ETrackedControllerRole
{
	TrackedControllerRole_Invalid = 0,      // Invalid value for controller type
	TrackedControllerRole_LeftHand = 1,     // Tracked device associated with the left hand
	TrackedControllerRole_RightHand = 2,    // Tracked device associated with the right hand
	TrackedControllerRole_OptOut = 3,       // Tracked device is opting out of left/right hand selection
	TrackedControllerRole_Treadmill = 4,    // Tracked device is a treadmill or other locomotion device
	TrackedControllerRole_Stylus = 5,       // Tracked device is a stylus
	TrackedControllerRole_Max = 5
};
				

One way Valve could implement this in a flexible way would be to allow parent/child relationships between tracked devices. A treadmill device would be a virtual tracked device whose position is updated by the treadmill movement. Then all "real" tracked devices (headset, controllers, etc.) could be "anchored" to the treadmill device so that their tracking position is added to the movement of the treadmill. As far as I know, there is no such functionality built into the API.

Before I discovered the proxy driver technique, there were a few ways I had considered, but they all have significant drawbacks:

  • Directional Input - Use Steam's input system to map the treadmill motion to the movement thumbstick input for the app. The treadmill basically acts as a controller, so this works as long as the app accepts thumbstick for player movement. The main issue is that the movement isn't 1:1 with the real world motion, so it would need to be calibrated separately for each app.
  • Application Interface - Modify the application to interface with the treadmill. This is a pretty bad option since it requires access to the code of the application or modding capability. It does allow for direct 1:1 mapping of motion though.
  • Chaperone Offset - Continuously update the origin offset of the chaperone (room tracking bounds) as the treadmill moves. This uses the room setup calibration system to make the application think that the room is moving around in the virtual space. This is the technique used by OpenVR Advanced Settings and I used it for my strip-based treadmill. It works fairly well, but has jitter problems and continuously adjusting the chaperone settings has a significant CPU cost.

The Solution

So none of those options totally solves the problem. What I really wanted was a system that would apply the treadmill position/velocity offsets to the headset/controller positions before they are sent to OpenVR. That way the tracked devices would appear to be moving through space as the treadmill moves. I was able to do exactly this by making a wrapper around the existing lighthouse driver to intercept all of the tracking updates.

Treadmill Simulator Test App
treadmill simulator test console application