Isaac Sim Version
5.1.0
5.0.0
4.5.0
4.2.0
4.1.0
4.0.0
4.5.0
2023.1.1
2023.1.0-hotfix.1
Other (please specify):
Operating System
Ubuntu 24.04
Ubuntu 22.04
Ubuntu 20.04
Windows 11
Windows 10
Other (please specify):
Topic Description
Hello,
I’m trying to retrieve the left and right controller pose values from a Meta Quest 2 in Isaac Sim 5.1, but it doesn’t seem to work properly.
The following script worked perfectly in Isaac Sim 5.0 (via the Script Editor), but when I run the same code in version 5.1, the printed values of left_pos and left_rot remain fixed at (0, 0, 0) and (1, 0, 0, 0).
I also confirmed that the prim paths "/_xr/inputdevices/user/hand/right/grip" and "/_xr/inputdevices/user/hand/left/grip" are correctly created in the stage.
I’d like to ask if there have been any changes in how VR device pose data is handled between versions 5.0 and 5.1.
Any advice or workaround to resolve this issue would be greatly appreciated.
Device: Meta Quest 2
Isaac Sim version: 5.1
ALVR streamer version: v20.14.1
SteamVR version: 2.12.14
Ubuntu version: 22.04
import omni
from pxr import Gf, UsdGeom, Usd
import math
stage = omni.usd.get_context().get_stage()
app = omni.kit.app.get_app()
time_code = Usd.TimeCode.Default()
left_path = "/_xr/inputdevices/user/hand/left/grip"
right_path = "/_xr/inputdevices/user/hand/right/grip"
# Create visualization prims for the controllers
def ensure_vis_prim(path, color):
if not stage.GetPrimAtPath(path):
prim = UsdGeom.Sphere.Define(stage, path)
prim.CreateRadiusAttr(0.03)
prim.CreateDisplayColorAttr([color])
return stage.GetPrimAtPath(path)
# Blue sphere for the left controller, orange for the right controller
left_vis = ensure_vis_prim("/World/LeftHandVis", (0.1, 0.6, 1.0)) # Blue
right_vis = ensure_vis_prim("/World/RightHandVis", (1.0, 0.4, 0.1)) # Orange
prev_left_pos, prev_right_pos = None, None
threshold = 0.05 # Movement threshold (5 cm)
def distance(a, b):
"""Compute Euclidean distance between two 3D points."""
return math.sqrt((a[0]-b[0])**2 + (a[1]-b[1])**2 + (a[2]-b[2])**2)
def get_world_pose(prim_path):
"""Return the world position and orientation (quaternion) of a prim."""
prim = stage.GetPrimAtPath(prim_path)
if not prim or not prim.IsValid():
return None, None
xformable = UsdGeom.Xformable(prim)
world_mat = xformable.ComputeLocalToWorldTransform(time_code)
pos = world_mat.ExtractTranslation()
rot = world_mat.ExtractRotation().GetQuat() # Quaternion (x, y, z, w)
return pos, rot
def update_vis_prim(prim, pos):
"""Move the visualization sphere to the given position."""
xformable = UsdGeom.Xformable(prim)
xformable.MakeMatrixXform().Set(Gf.Matrix4d().SetTranslate(pos))
def on_update(e):
"""Main update callback — runs every frame."""
global prev_left_pos, prev_right_pos
# ---- Left hand ----
left_pos, left_rot = get_world_pose(left_path)
print(left_pos, left_rot)
if left_pos:
update_vis_prim(left_vis, left_pos)
if prev_left_pos is None:
prev_left_pos = left_pos
elif distance(left_pos, prev_left_pos) > threshold:
print(f"🕹 Left moved → {left_pos}")
print(f" rotation (quat): {left_rot}")
prev_left_pos = left_pos
# ---- Right hand ----
right_pos, right_rot = get_world_pose(right_path)
if right_pos:
update_vis_prim(right_vis, right_pos)
if prev_right_pos is None:
prev_right_pos = right_pos
elif distance(right_pos, prev_right_pos) > threshold:
print(f"🎮 Right moved → {right_pos}")
print(f" rotation (quat): {right_rot}")
prev_right_pos = right_pos
# Subscribe to the app's update event stream
sub = app.get_update_event_stream().create_subscription_to_pop(on_update)
print("✅ VR tracking + visualization active — move > 5 cm to log movement.")
Thank you so much for your help!

