Deprecation Notice: Switch to pyopenxr
mainpyopenxr at https://github.com/cmbruns/pyopenxr.repository·main·Indexed 43 days ago
https://github.com/cmbruns/pyopenvrUnofficial Python bindings for Valve's OpenVR virtual reality SDK, enabling interaction with VR hardware and SteamVR. Provides access to core interfaces such as VRSystem, VRCompositor, VROverlay, and VRInput, along with constants and data structures for device poses, event polling, and tracked device properties. Note: This library is being superseded by OpenXR; users are encouraged to switch to pyopenxr.
pyopenxr at https://github.com/cmbruns/pyopenxr.To use pyopenvr, ensure you have the following prerequisites installed:
Then, install the bindings using pip or by downloading the installer from the official releases page.
pip install openvrWhen OpenVR functions return a failure code, pyopenvr raises specific Python exceptions derived from OpenVRError. Instead of catching a generic Exception, you can catch OpenVRError or more specific error subclasses to handle different failure modes precisely.
To convert a raw error value (integer) into its corresponding Python exception class, use the check_error_value class method on an ErrorCode subclass.
from openvr.error_code import TrackedPropertyError
# Example of checking an error value returned from an OpenVR call
try:
# Assume error_val is an integer returned by a C++ binding
TrackedPropertyError.check_error_value(error_val, "Failed to read property")
except TrackedPropertyError as e:
print(f"OpenVR Tracked Property Error: {e}")
except OpenVRError as e:
print(f"General OpenVR Error: {e}")OpenVR uses a union-based event system. When an event is polled via IVRSystem.pollNextEvent, the resulting VREvent_t structure contains an eventType and a data field. The data field is a VREvent_Data_t union, which holds the specific details for that event type.
Common event data structures include:
VREvent_Controller_t: For controller button events.VREvent_Mouse_t: For simulated mouse events in overlay space.VREvent_TouchPadMove_t: For touchpad movement data.VREvent_Overlay_t: For events related to overlays.VREvent_HapticVibration_t: For haptic feedback events.VREvent_Screenshot_t: For screenshot related events.To use them, check the eventType and then access the corresponding field in the data union.
import openvr
vr_system = openvr.VRSystem()
event = openvr.VREvent_t()
# Polling an event
if vr_system.pollNextEvent(event, 0x00000001): # Example mask
if event.eventType == openvr.EVREventType.ControllerButton:
button_id = event.data.controller.button
elif event.eventType == openvr.EVREventType.Mouse:
mouse_x = event.data.mouse.x
mouse_y = event.data.mouse.yTo use the OpenVR API, you must first initialize the runtime. Use init(applicationType, pStartupInfo=None) to find the active installation and initialize it. This returns a VRSystem instance. To release resources and unload the library, call shutdown().
Note on pStartupInfo: If provided, this must be an absolute or relative path to the "root" of the VR API install (the directory containing the drivers directory and a platform directory, not just the DLL location).
import openvr
# Initialize OpenVR
system = openvr.init(openvr.EVRApplicationType.VRApplication_Application)
# ... use system ...
# Shutdown OpenVR
openvr.shutdown()To use pyopenvr, you must initialize the VR system using openvr.init() with an appropriate application type (e.g., openvr.VRApplication_Scene). After performing your VR operations, always call openvr.shutdown() to release resources.
In the main loop, you can use openvr.VRCompositor().waitGetPoses() to retrieve device poses, such as the HMD pose, which can be accessed via the openvr.k_unTrackedDeviceIndex_Hmd index.
import sys
import time
import openvr
openvr.init(openvr.VRApplication_Scene)
poses = [] # will be populated with proper type after first call
for i in range(100):
poses, _ = openvr.VRCompositor().waitGetPoses(poses, None)
hmd_pose = poses[openvr.k_unTrackedDeviceIndex_Hmd]
print(hmd_pose.mDeviceToAbsoluteTracking)
sys.stdout.flush()
time.sleep(0.2)
openvr.shutdown()The Overlay interface allows you to create and manage 2D elements in the VR space. You can set textures, handle mouse/laser intersections, and manage cursors.
setOverlayTexture to provide a texture for the overlay. Note that this can only be called by the overlay's creator or renderer process.computeOverlayIntersection to find where a ray intersects the overlay in pixel coordinates.setOverlayCursor to change the default blob to a custom cursor, and setOverlayCursorPositionOverride to manually position the cursor.triggerLaserMouseHapticVibration.Dashboard overlays are special overlays that appear when the user opens the SteamVR dashboard.
createDashboardOverlay(overlayKey, overlayFriendlyName) to create a new dashboard overlay. It returns a mainHandle and a thumbnailHandle.isDashboardVisible() or if a specific overlay is the active one using isActiveDashboardOverlay(overlayHandle).setDashboardOverlaySceneProcess(overlayHandle, processId) to ensure the overlay only appears when a specific process has scene focus.The IVROverlayView interface allows you to acquire read privileges over an overlay's contents to sample them.
acquireOverlayView(overlayHandle) to get a VROverlayView_t and a VRNativeDevice_t.releaseOverlayView() to release the acquired resources. Failure to do so will leak GPU resources.The IVRRenderModels interface is used to load and interact with 3D models representing tracked devices (like controllers).
loadRenderModel_Async(renderModelName) to load a model. It returns a RenderModel_t pointer. The method returns VRRenderModelError_Loading while the model is still loading.freeRenderModel(renderModel) when finished to prevent memory leaks.getComponentCount(renderModelName) and getComponentName(renderModelName, componentIndex) to iterate through them.getComponentStateForDevicePath(renderModelName, componentName, devicePath, state) to query the current state (position, motion, etc.) of a specific component.The IVROverlay class provides the API for creating, managing, and transforming 2D overlays in VR space. Overlays can be standalone quads, subviews composited onto parent overlays, or projection overlays.
createOverlay(overlayKey, overlayName) to create a new named overlay. It starts hidden by default.findOverlay(overlayKey) to retrieve a handle for an existing overlay using its unique key.destroyOverlay(overlayHandle) to remove an overlay. Overlays are automatically destroyed when the application calls VR_Shutdown.showOverlay(overlayHandle) and hideOverlay(overlayHandle) to control visibility. Use isOverlayVisible(overlayHandle) to check the current state.Subviews are separate images composited onto a parent overlay based on a 2D transform. They can only be created for parent overlays owned by the same process.
createSubviewOverlay(parentOverlayHandle, subviewOverlayKey, subviewOverlayName)setSubviewPosition(overlayHandle, x, y) positions the subview in the pixel coordinate space of the parent overlay (top-left is 0,0).getOverlayKey(overlayHandle), getOverlayName(overlayHandle), and setOverlayName(overlayHandle, name).setOverlayColor(overlayHandle, red, green, blue) (values 0.0 to 1.0) and setOverlayAlpha(overlayHandle, alpha) to adjust appearance.setOverlayWidthInMeters(overlayHandle, widthInMeters). The default is 1 meter.setOverlayCurvature(overlayHandle, curvature) to draw the overlay as a curved surface (0..1, where 1 is a closed cylinder). Use setOverlayPreCurvePitch(overlayHandle, radians) to adjust the pitch before curvature is applied.overlay = ivroverlay.createOverlay("my_key", "My Overlay")
ivroverlay.setOverlayWidthInMeters(overlay, 2.0)
ivroverlay.showOverlay(overlay)Retrieves the next event from the OpenVR event queue.
pollNextEvent(event): Fills the provided event struct with the next event. Returns True if an event was available, False otherwise.pollNextEventWithPose(origin, event): Fills the event and also provides the pose of the associated tracked device in a provided pose struct. Note that this pose will be older than the call time and should not be used for rendering.pollNextEventWithPoseAndOverlays(origin, event): An efficient way to poll both system events and overlay-specific events (like button presses on an overlay). If an event is targeted at a specific overlay, pulOverlayHandle will be set.# Example: Polling for a standard event
event = VREvent_t()
if vr_system.pollNextEvent(event):
print(f"Event type: {vr_system.getEventTypeNameFromEnum(event.eventType)}")