mirror of
https://github.com/Rulez777/FramePicoTracker.git
synced 2026-10-19 00:01:28 +02:00
77 lines
2.4 KiB
Python
77 lines
2.4 KiB
Python
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
# Copyright (C) 2026 L8OLOOE and contributors. See CREDITS.md and NOTICE.md.
|
|
"""Virtual Motion Tracker (VMT) OSC Client.
|
|
|
|
Sends OpenVR tracker poses to SteamVR via VMT's OSC UDP interface.
|
|
Default VMT port: 39570 (UDP).
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
from pythonosc.udp_client import SimpleUDPClient
|
|
import numpy as np
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
DEFAULT_VMT_HOST = "127.0.0.1"
|
|
DEFAULT_VMT_PORT = 39570
|
|
|
|
|
|
class VMTClient:
|
|
"""Client for Virtual Motion Tracker (VMT) in SteamVR."""
|
|
|
|
def __init__(self, host: str = DEFAULT_VMT_HOST, port: int = DEFAULT_VMT_PORT) -> None:
|
|
self.host = host
|
|
self.port = port
|
|
self.client = SimpleUDPClient(host, port)
|
|
logger.info("VMTClient initialized targeting %s:%d", host, port)
|
|
|
|
def send_pose(
|
|
self,
|
|
index: int,
|
|
pos: np.ndarray,
|
|
quat: np.ndarray,
|
|
enabled: bool = True,
|
|
time_offset: float = 0.0,
|
|
room_space: bool = True,
|
|
) -> None:
|
|
"""Send tracker pose to SteamVR.
|
|
|
|
Args:
|
|
index: Tracker index (0, 1, 2, ...).
|
|
pos: 3D position [x, y, z] in meters (OpenVR right-handed coordinate system).
|
|
quat: Quaternion [qx, qy, qz, qw] (OpenVR right-handed).
|
|
enabled: Whether tracker is active and tracked.
|
|
time_offset: Prediction or delay compensation in seconds (0.0 = current).
|
|
room_space: True to use /vmt/set/room/pose, False to use /vmt/set/raw/pose.
|
|
"""
|
|
address = "/vmt/set/room/pose" if room_space else "/vmt/set/raw/pose"
|
|
px, py, pz = float(pos[0]), float(pos[1]), float(pos[2])
|
|
qx, qy, qz, qw = float(quat[0]), float(quat[1]), float(quat[2]), float(quat[3])
|
|
|
|
args = [
|
|
int(index),
|
|
1 if enabled else 0,
|
|
float(time_offset),
|
|
px,
|
|
py,
|
|
pz,
|
|
qx,
|
|
qy,
|
|
qz,
|
|
qw,
|
|
]
|
|
self.client.send_message(address, args)
|
|
|
|
def send_diag(self, index: int, message: str) -> None:
|
|
"""Send diagnostic/battery message for tracker."""
|
|
self.client.send_message("/vmt/set/diag", [int(index), str(message)])
|
|
|
|
def disable_tracker(self, index: int) -> None:
|
|
"""Disable tracker in SteamVR."""
|
|
self.client.send_message(
|
|
"/vmt/set/room/pose",
|
|
[int(index), 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0],
|
|
)
|