API Reference
ContactGlove Python SDK is a Python library for working with ContactGlove.
Requirements
The supported language is Python 3.10 or later.
The SDK itself is pure Python and does not require an OS-specific build. Operation has been confirmed on Windows 11, macOS, and Ubuntu. Check the viewer setup and DivingStation availability separately.
DivingStation must be installed and running beforehand.
This library depends on the following packages.
| Package Name | version |
|---|---|
| python-osc | >=1.7.5 |
| matplotlib | >=3.7.5 (used only by examples/viewer) |
Installation
Save the distribution package on your computer and extract it, then install the bundled wheel file from the extracted folder.
python -m pip install ./contactglovesdk-X.Y.Z-py3-none-any.whlpip installs the dependencies (python-osc, matplotlib, and so on)
automatically.
Usage
Connecting to and disconnecting from DivingStation
Use the ContactGloveClient.connect_to_host method to connect to DivingStation.
The Host passed to connect_to_host carries three pieces of information: a host name, an IP address, and the receive port on the DivingStation side. The host name is chosen freely by the user to tell hosts apart. The IP address is the one assigned to the computer that runs DivingStation. The DivingStation receive port is the port on which DivingStation receives OSC requests from the SDK. It is normally 25791, but it can be changed in DivingStation; set it to the matching value if you do.
The receive port on the SDK (local) side is specified by the local_port constructor argument of ContactGloveClient. Passing 0 (the default) lets the OS assign a free port automatically, which you can read from the client.local_port property after connecting.
The source port used when sending OSC commands to DS is specified by the send_port constructor argument. Passing 0 (the default) lets the OS assign a free port. After the first send (for example a connect), the actual port number is available from the client.send_port property.
To retry while waiting for LAN approval or recovering from missing data, call connect_to_host(host) again on the same client without calling disconnect or close. It resends Connect from the same send socket and keeps the receive port, including when send_port=0. The SDK also resends Connect every 30 seconds automatically. A successful call does not confirm LAN approval. After DivingStation restarts, retries can restore the session; approve it again in DivingStation if required. Explicit Disconnect ends the session and can revoke pending or granted approval.
Use the disconnect method to close the connection to DivingStation. As the shutdown step for the whole SDK, close() (or the context manager form via a with statement) stops the local server and the send socket.
from contactglovesdk import ContactGloveClient, Host
host = Host("localhost", "127.0.0.1", 25791)
with ContactGloveClient() as client:
# Connect to DivingStation
client.connect_to_host(host)
# Do various things
# Disconnect from DivingStation
client.disconnect(host)Reading values
There are methods for reading the various kinds of glove-related information. The value returned is the most recent data received as of the moment of the call. The available values and methods are as follows.
| Available value | Method name |
|---|---|
| Information about the glove itself | get_data_for_glove |
| Whether the glove supports haptics | does_glove_support_haptics |
| Opening/bending angle of each finger joint | get_ergonomics_data_for_glove |
| Position/rotation of each finger joint | get_skeleton_data_for_glove |
| Position/rotation of the raw sensors | get_rawsensor_data_for_glove |
| Input from the controller attached to the glove | get_controller_data_for_glove |
| IDs of all connected gloves | get_ids_of_available_gloves |
| Total number of connected gloves | get_number_of_available_gloves |
Glove data arrives asynchronously. Register a callback before connecting to learn an actual glove ID, then wait for data before polling. The connection call starts the local session; it does not confirm that DivingStation has approved the connection or sent data.
from threading import Event
from contactglovesdk import ContactGloveClient, DeviceConnectedState, Host, InvalidIDError
host = Host("localhost", "127.0.0.1", 25791)
received = Event()
glove_ids = []
def on_glove(glove):
if glove.connected_state == DeviceConnectedState.Connected and not received.is_set():
glove_ids.append(glove.id)
received.set()
with ContactGloveClient() as client:
client.register_callback_for_glove_data_stream(on_glove)
client.connect_to_host(host)
try:
if received.wait(timeout=5):
try:
glove = client.get_data_for_glove(glove_ids[0])
print(f"id={glove.id}")
except InvalidIDError:
print("The glove is no longer available")
else:
print("No glove data received within 5 seconds")
finally:
client.disconnect(host)If data does not arrive, check that the glove is connected and enabled in DivingStation and that any required connection approval has been granted. For multiple gloves, select the intended ID rather than assuming the first one is the desired glove.
Following value changes automatically
You can register callbacks that are invoked automatically whenever the various glove-related values are updated. Callbacks are invoked from the OSC receive thread, so implement the work inside a callback on the assumption that it is accessed from multiple threads. If a callback raises an exception, the SDK logs it with its traceback to the contactglovesdk logger (shown on stderr when logging is not configured) and keeps invoking the other callbacks.
| Value that triggers the call | Method name |
|---|---|
| Information about the glove itself | register_callback_for_glove_data_stream |
| Opening/bending angle of each finger joint | register_callback_for_ergonomics_stream |
| Position/rotation of each finger joint | register_callback_for_skeleton_stream |
| Position/rotation of the raw sensors | register_callback_for_rawsensor_stream |
| Input from the controller attached to the glove | register_callback_for_controller_data_stream |
They are used as follows.
import time
from contactglovesdk import ContactGloveClient, GloveData, Host
host = Host("localhost", "127.0.0.1", 25791)
def on_glove(g: GloveData) -> None:
print(f"[callback] id={g.id} battery={g.battery_percentage}%"
f" left={g.is_left} state={g.connected_state.name}")
with ContactGloveClient() as client:
# Registering callbacks before connecting avoids missing updates
client.register_callback_for_glove_data_stream(on_glove)
client.connect_to_host(host)
# Wait for 5 seconds
time.sleep(5)
client.disconnect(host)Haptics
The vibrate_glove method sends a vibration command to a glove that has the haptics feature. The command is sent to every DS host that is currently connected. Replace YOUR_GLOVE_ID with the actual ID received from DivingStation.
client.vibrate_glove("YOUR_GLOVE_ID", frequency=200.0, amplitude=0.8, duration=0.2)Defined types and functions
The types and functions that this SDK defines and makes available are as follows.
Classes
| Name | Description |
|---|---|
ContactGloveClient | Main class of ContactGlove SDK v2 |
Host | Data class holding the host information of DivingStation |
GloveData | Data class holding the information of a glove device |
ControllerData | Data class holding the input state of the controller |
ErgonomicsData | Data class holding the finger opening and bending angle data |
SkeletonData | Data class holding the hand skeleton data (joint positions and rotations) |
RawSkeletonData | Data class holding the hand skeleton data before retargeting. |
RawSensorData | Data class holding the raw sensor Transform data for one hand |
RetargetProfileInfo | Data class holding the response that carries retarget profile information. |
Transform | Transform combining a position and a rotation |
Vec3 | Three-dimensional vector |
Quaternion | Quaternion representing a rotation |
Enumerations
| Name | Description |
|---|---|
DeviceFamilyType | Enum representing the kind of device |
DeviceColor | Enum representing the device display-color setting |
DeviceConnectedState | Enum representing the connection state of the device |
ButtonStatus | Enum representing the press state of a button |
TrackingState | Enum representing the tracking state of IK-derived data. |
ErgonomicsIndex | Enum indicating the joint that each element of ErgonomicsData.values represents |
SkeletonNode | Enum indicating the joint that each element of SkeletonData.positions represents |
SkeletonRotationNode | Enum indicating the joint that each element of SkeletonData.rotations represents |
RawSensorIndex | Enum indicating the sensor that each element of RawSensorData.transforms represents |
Exceptions
| Name | Description |
|---|---|
ContactGloveSDKError | Base class for the exceptions raised by the SDK |
SDKNotAvailableError | Raised when opening a local UDP socket fails (for example because the port is in use) |
NotConnectedError | Raised when an operation that requires a connection is attempted while that connection does not exist |
InvalidIDError | Raised when no data for the specified glove ID exists in the current data store |
Constants
| Name | Value | Description |
|---|---|---|
ERGONOMICS_COUNT | 20 | Number of ergonomics data elements per hand (5 fingers × 4 joints) |
SKELETON_NODE_COUNT | 25 | Number of skeleton position elements per hand |
SKELETON_ROTATION_COUNT | 19 | Number of skeleton rotation elements per hand (the wrist and the 5 fingertip nodes are excluded) |
RAW_SENSOR_COUNT | 5 | Number of raw sensor Transforms per hand (one per finger) |
DeviceFamilyType
class DeviceFamilyType(IntEnum)Enum representing the kind of device
Corresponds to the device_type field of /DS2/HC/Device.
ContactGlove3 is the primary target.
| Value | Description |
|---|---|
ContactGlove | ContactGlove |
ContactSheet | ContactSheet |
ContactGlove2 | ContactGlove2 |
ContactGlove3 | ContactGlove3 |
DeviceColor
class DeviceColor(IntEnum)Enum representing the device display-color setting
Corresponds to the color field of /DS2/HC/Device.
Migrating the display-color type name
The public display-color type is DeviceColor. Replace the old import with
from contactglovesdk import DeviceColor and update references such as
LedColor.Green to DeviceColor.Green. The GloveData.color field name,
numeric color values, and OSC wire format stay the same.
LedColor remains an exported compatibility alias of DeviceColor, so
existing imports still work. Prefer DeviceColor for new code.
Serialized enum values retain the LedColor identity for interoperability
with older processes.
| Value | Description |
|---|---|
Magenta | Magenta |
Red | Red |
Orange | Orange |
Yellow | Yellow |
Green | Green |
Cyan | Cyan |
Blue | Blue |
Achromatic | Achromatic |
DeviceConnectedState
class DeviceConnectedState(IntEnum)Enum representing the connection state of the device
Corresponds to the connected_state field of /DS2/HC/Device.
| Value | Description |
|---|---|
Unknown | State unknown |
Connected | Connected |
Unconnected | Not connected |
Pairing | Attempting to connect |
ButtonStatus
class ButtonStatus(IntEnum)Enum representing the press state of a button
Corresponds to each button field of /DS2/HC/Controller.
| Value | Description |
|---|---|
Unpressed | Not pressed |
Touching | Touched (detected by the touch sensor) |
Pressed | Pressed |
TrackingState
class TrackingState(IntEnum)Enum representing the tracking state of IK-derived data.
Corresponds to the tracking_state field of /DS2/HC/Ergonomics,
/DS2/HC/HandSkeleton and /DS2/HC/HandSkeletonRaw.
Values marked IkFailed or NotAttempted may be used for display and
diagnostics, but must not be used for control, velocity estimation or
interpolation. Only Tracked values are valid for those uses.
NotAttempted means the required IK pass was not performed. It includes
earlier processing failures or missing input, and cases where pose calculation
was deemed unnecessary, such as update-interval control reusing an existing
pose. This state does not itself indicate an IK failure.
SkeletonData reports retarget IK; RawSkeletonData and ErgonomicsData
report source-skeleton IK. Their states can differ at the same time.
| Value | Description |
|---|---|
Tracked | A valid value obtained from the current IK pass |
IkFailed | A value for which the IK pass was attempted but failed |
NotAttempted | A value for which IK was not performed, including intentional update-interval skips as well as earlier failures or missing input |
ErgonomicsIndex
class ErgonomicsIndex(IntEnum)Enum indicating the joint that each element of ErgonomicsData.values represents
The indices cover one hand (ERGONOMICS_COUNT = 20 elements), and
values[i] corresponds to ErgonomicsIndex(i). Values are in degrees,
and a bending angle is 0 degrees when the finger is extended.
| Value | Description |
|---|---|
ThumbCMC | Bending angle of the thumb CMC joint |
ThumbMCP | Bending angle of the thumb MCP joint |
ThumbIP | Bending angle of the thumb IP joint |
ThumbTilt | Tilt angle of the thumb MCP joint |
IndexMCP | Bending angle of the index finger MCP joint |
IndexPIP | Bending angle of the index finger PIP joint |
IndexDIP | Bending angle of the index finger DIP joint |
IndexTilt | Tilt angle of the index finger MCP joint |
MiddleMCP | Bending angle of the middle finger MCP joint |
MiddlePIP | Bending angle of the middle finger PIP joint |
MiddleDIP | Bending angle of the middle finger DIP joint |
MiddleTilt | Tilt angle of the middle finger MCP joint |
RingMCP | Bending angle of the ring finger MCP joint |
RingPIP | Bending angle of the ring finger PIP joint |
RingDIP | Bending angle of the ring finger DIP joint |
RingTilt | Tilt angle of the ring finger MCP joint |
LittleMCP | Bending angle of the little finger MCP joint |
LittlePIP | Bending angle of the little finger PIP joint |
LittleDIP | Bending angle of the little finger DIP joint |
LittleTilt | Tilt angle of the little finger MCP joint |
SkeletonNode
class SkeletonNode(IntEnum)Enum indicating the joint that each element of SkeletonData.positions represents
The indices cover one hand (SKELETON_NODE_COUNT = 25 elements), and
positions[i] corresponds to SkeletonNode(i).
| Value | Description |
|---|---|
Wrist | Wrist |
ThumbCMC | Thumb CMC joint |
ThumbMCP | Thumb MCP joint |
ThumbIP | Thumb IP joint |
ThumbTip | Thumb tip |
IndexCMC | Index finger CMC joint |
IndexMCP | Index finger MCP joint |
IndexPIP | Index finger PIP joint |
IndexDIP | Index finger DIP joint |
IndexTip | Index finger tip |
MiddleCMC | Middle finger CMC joint |
MiddleMCP | Middle finger MCP joint |
MiddlePIP | Middle finger PIP joint |
MiddleDIP | Middle finger DIP joint |
MiddleTip | Middle finger tip |
RingCMC | Ring finger CMC joint |
RingMCP | Ring finger MCP joint |
RingPIP | Ring finger PIP joint |
RingDIP | Ring finger DIP joint |
RingTip | Ring finger tip |
LittleCMC | Little finger CMC joint |
LittleMCP | Little finger MCP joint |
LittlePIP | Little finger PIP joint |
LittleDIP | Little finger DIP joint |
LittleTip | Little finger tip |
SkeletonRotationNode
class SkeletonRotationNode(IntEnum)Enum indicating the joint that each element of SkeletonData.rotations represents
The indices cover one hand (SKELETON_ROTATION_COUNT = 19 elements), and
rotations[i] corresponds to SkeletonRotationNode(i).
Unlike SkeletonNode, the wrist and the 5 fingertip nodes are excluded
because they carry no rotation value.
| Value | Description |
|---|---|
ThumbCMC | Thumb CMC joint |
ThumbMCP | Thumb MCP joint |
ThumbIP | Thumb IP joint |
IndexCMC | Index finger CMC joint |
IndexMCP | Index finger MCP joint |
IndexPIP | Index finger PIP joint |
IndexDIP | Index finger DIP joint |
MiddleCMC | Middle finger CMC joint |
MiddleMCP | Middle finger MCP joint |
MiddlePIP | Middle finger PIP joint |
MiddleDIP | Middle finger DIP joint |
RingCMC | Ring finger CMC joint |
RingMCP | Ring finger MCP joint |
RingPIP | Ring finger PIP joint |
RingDIP | Ring finger DIP joint |
LittleCMC | Little finger CMC joint |
LittleMCP | Little finger MCP joint |
LittlePIP | Little finger PIP joint |
LittleDIP | Little finger DIP joint |
RawSensorIndex
class RawSensorIndex(IntEnum)Enum indicating the sensor that each element of RawSensorData.transforms represents
The indices cover one hand (RAW_SENSOR_COUNT = 5 elements), and
transforms[i] corresponds to RawSensorIndex(i).
| Value | Description |
|---|---|
Thumb | Thumb |
Index | Index finger |
Middle | Middle finger |
Ring | Ring finger |
Little | Little finger |
ERGONOMICS_COUNT
ERGONOMICS_COUNT: int = 20Number of ergonomics data elements per hand (5 fingers × 4 joints)
SKELETON_NODE_COUNT
SKELETON_NODE_COUNT: int = 25Number of skeleton position elements per hand
SKELETON_ROTATION_COUNT
SKELETON_ROTATION_COUNT: int = 19Number of skeleton rotation elements per hand (the wrist and the 5 fingertip nodes are excluded)
RAW_SENSOR_COUNT
RAW_SENSOR_COUNT: int = 5Number of raw sensor Transforms per hand (one per finger)
ContactGloveClient
from contactglovesdk import ContactGloveClientMain class of ContactGlove SDK v2
Polling results and each stream callback receive independent snapshots, including nested lists and geometry values. Modifying one does not change the SDK cache or values delivered to other callbacks.
Usage:
import time
from contactglovesdk import ContactGloveClient, Host, InvalidIDError
host = Host("localhost", "127.0.0.1", 25791)
with ContactGloveClient() as client:
# Register before connecting so the first update is not missed.
client.register_callback_for_glove_data_stream(
lambda g: print(g.id, g.battery_percentage)
)
client.connect_to_host(host)
try:
# Poll until an ID arrives or the five-second deadline expires.
deadline = time.monotonic() + 5.0
glove_ids = client.get_ids_of_available_gloves()
while not glove_ids and time.monotonic() < deadline:
time.sleep(0.1)
glove_ids = client.get_ids_of_available_gloves()
if glove_ids:
try:
glove = client.get_data_for_glove(glove_ids[0])
print(glove.id)
except InvalidIDError:
print("The glove is no longer available")
else:
print("No glove data received within 5 seconds")
finally:
client.disconnect(host)Public Methods
| Return | Name | Description |
|---|---|---|
__init__ | Main class of ContactGlove SDK v2 | |
int | start_server | Start the local OSC server without connecting to any host. |
int | None | local_port | Port number used by the local OSC server. None while it is not running. |
int | None | send_port | Port number used by the OSC send socket. None before the first send. |
None | close | Stop the local OSC server and the send socket. |
None | connect_to_host | Connect to DivingStation and start the data streams. |
None | disconnect | Disconnect from a DS. |
bool | does_glove_support_haptics | Check whether the glove supports haptics. |
GloveData | get_data_for_glove | Read the glove information for a glove ID. |
ControllerData | get_controller_data_for_glove | Read the controller input data for a glove ID. |
ErgonomicsData | get_ergonomics_data_for_glove | Read the finger opening and bending angle data for a glove ID. |
SkeletonData | get_skeleton_data_for_glove | Read the joint position and rotation data for a glove ID. |
RawSkeletonData | get_raw_skeleton_data_for_glove | Read the pre-retarget hand skeleton for a glove ID. |
RawSensorData | get_rawsensor_data_for_glove | Read the raw sensor Transform data for a glove ID. |
list[str] | get_ids_of_available_gloves | Read the IDs of every glove that is currently known. |
int | get_number_of_available_gloves | Read the total number of gloves that are currently known. |
None | vibrate_glove | Make the glove vibrate. |
None | request_retarget_profile_info | Request the display name and description of a retarget profile from DivingStation. |
None | register_callback_for_glove_data_stream | Register a callback invoked when the glove information is updated. |
None | register_callback_for_controller_data_stream | Register a callback invoked when the controller data is updated. |
None | register_callback_for_ergonomics_stream | Register a callback invoked when the ergonomics data is updated. |
None | register_callback_for_skeleton_stream | Register a callback invoked when the skeleton data is updated. |
None | register_callback_for_raw_skeleton_stream | Register a callback invoked when the pre-retarget skeleton is updated. |
None | register_callback_for_rawsensor_stream | Register a callback invoked when the raw sensor Transform data is updated. |
None | register_callback_for_retarget_profile_info_stream | Register a callback that receives the retarget profile information response. |
Class Attributes
| Return | Name | Description |
|---|---|---|
int | DEFAULT_DS_PORT | Default OSC receive port number on the DivingStation side |
__init__
ContactGloveClient(local_host: str = "0.0.0.0", local_port: int = 0, send_port: int = 0)Parameters
-
local_hostNetwork interface the local OSC server binds to ("0.0.0.0"for every interface). -
local_portPort number the local OSC server binds to (0lets the OS pick a free port automatically). -
send_portLocal UDP port number used to send OSC to DS (0lets the OS pick a free port automatically).
start_server
def start_server(self) -> intStart the local OSC server without connecting to any host.
Use this when the local port number is needed before calling
connect_to_host.
Returns
The port number the server actually bound to.
Raises
SDKNotAvailableErrorIf binding the port failed.
local_port
@property
def local_port(self) -> int | NonePort number used by the local OSC server. None while it is not running.
send_port
@property
def send_port(self) -> int | NonePort number used by the OSC send socket. None before the first send.
close
def close(self)Stop the local OSC server and the send socket.
If any stream callback is still running, this waits for it to finish before returning.
connect_to_host
def connect_to_host(self, host: Host)Connect to DivingStation and start the data streams.
Starts the local OSC server if it is not running yet, then sends
/DS2/HC/Connect <local_port> to host. While the connection is kept
alive, Connect is re-sent every 30 seconds from the same send socket.
Calling again for the same IP address and DS port resends Connect
without sending Disconnect or replacing the send socket, receive port,
or keepalive worker. Use this to retry while awaiting LAN approval or
recovering from lost data. The OS-selected source port is retained even
when send_port is 0. Returning does not confirm LAN approval.
After DS restarts, Connect retries can restore the session; approve it
again in DS if required. Explicit disconnect ends the session and can
revoke pending or granted approval.
Parameters
hostHost information of the DS to connect to.
Raises
SDKNotAvailableErrorIf binding the local receive or send port failed.
disconnect
def disconnect(self, host: Host)Disconnect from a DS.
Sends /DS2/HC/Disconnect <local_port> to host. When the last
connection is closed, this waits until the stream callbacks that are
still running have finished.
Parameters
hostThe same host information that was passed toconnect_to_host.
Raises
NotConnectedErrorIf no connection to the given host exists.
does_glove_support_haptics
def does_glove_support_haptics(self, glove_id: str) -> boolCheck whether the glove supports haptics.
Parameters
glove_idID of the glove to check.
Returns
Whether the haptics feature is present.
Raises
InvalidIDErrorIf no glove with the given ID exists.
get_data_for_glove
def get_data_for_glove(self, glove_id: str) -> GloveDataRead the glove information for a glove ID.
Parameters
glove_idID of the glove to read.
Returns
A snapshot of the glove information.
Raises
InvalidIDErrorIf no glove with the given ID exists.
get_controller_data_for_glove
def get_controller_data_for_glove(self, glove_id: str) -> ControllerDataRead the controller input data for a glove ID.
Parameters
glove_idID of the glove to read.
Returns
A snapshot of the controller input data.
Raises
InvalidIDErrorIf no data for the given ID has been received yet.
get_ergonomics_data_for_glove
def get_ergonomics_data_for_glove(self, glove_id: str) -> ErgonomicsDataRead the finger opening and bending angle data for a glove ID.
Parameters
glove_idID of the glove to read.
Returns
A snapshot of the ergonomics data.
Raises
InvalidIDErrorIf no data for the given ID has been received yet.
get_skeleton_data_for_glove
def get_skeleton_data_for_glove(self, glove_id: str) -> SkeletonDataRead the joint position and rotation data for a glove ID.
Parameters
glove_idID of the glove to read.
Returns
A snapshot of the skeleton data.
Raises
InvalidIDErrorIf no data for the given ID has been received yet.
get_raw_skeleton_data_for_glove
def get_raw_skeleton_data_for_glove(self, glove_id: str) -> RawSkeletonDataRead the pre-retarget hand skeleton for a glove ID.
Returns
An independent snapshot, including positions and rotations.
Raises
InvalidIDErrorIf no data for the given ID has been received yet.
get_rawsensor_data_for_glove
def get_rawsensor_data_for_glove(self, glove_id: str) -> RawSensorDataRead the raw sensor Transform data for a glove ID.
Parameters
glove_idID of the glove to read.
Returns
A snapshot of the raw sensor Transform data.
Raises
InvalidIDErrorIf no data for the given ID has been received yet.
get_ids_of_available_gloves
def get_ids_of_available_gloves(self) -> list[str]Read the IDs of every glove that is currently known.
Returns
A list of glove IDs.
get_number_of_available_gloves
def get_number_of_available_gloves(self) -> intRead the total number of gloves that are currently known.
Returns
The total number of gloves.
vibrate_glove
def vibrate_glove(self, glove_id: str, frequency: float, amplitude: float, duration: float)Make the glove vibrate.
The command is sent to every DS host that is currently connected.
Parameters
-
glove_idID of the glove to vibrate. -
frequencyVibration frequency (Hz, 100.0 to 500.0). -
amplitudeVibration amplitude (0.0 to 1.0). -
durationVibration duration (seconds, 0.001 to 1.0).
Raises
-
InvalidIDErrorIf no glove with the given ID exists. -
ValueErrorIf frequency, amplitude or duration is outside the range of the specification or is not a finite value.
request_retarget_profile_info
def request_retarget_profile_info(self, profile_uuid: str, request_id: int)Request the display name and description of a retarget profile from DivingStation.
The response is delivered to the callback registered with
register_callback_for_retarget_profile_info_stream.
Parameters
-
profile_uuidThe 36-character UUID to query. -
request_idSigned 32-bit integer that correlates a request with its response.
Raises
ValueErrorIf the UUID or the request ID does not match the format of the protocol.
register_callback_for_glove_data_stream
def register_callback_for_glove_data_stream(self, callback: Callable[[GloveData], None])Register a callback invoked when the glove information is updated.
Every time /DS2/HC/Device is received, the callback is invoked with
the updated GloveData as its argument. The callback is invoked from
the OSC receive thread. Records whose connected_state is
Unconnected are passed as well, but the data for that ID can no
longer be read at that point.
Exceptions raised by the callback are logged to the contactglovesdk
logger and do not prevent other callbacks from being invoked.
Parameters
callbackCallback function to register.
register_callback_for_controller_data_stream
def register_callback_for_controller_data_stream(self, callback: Callable[[ControllerData], None])Register a callback invoked when the controller data is updated.
Exceptions raised by the callback are logged to the contactglovesdk
logger and do not prevent other callbacks from being invoked.
Parameters
callbackCallback function to register.
register_callback_for_ergonomics_stream
def register_callback_for_ergonomics_stream(self, callback: Callable[[ErgonomicsData], None])Register a callback invoked when the ergonomics data is updated.
Exceptions raised by the callback are logged to the contactglovesdk
logger and do not prevent other callbacks from being invoked.
Parameters
callbackCallback function to register.
register_callback_for_skeleton_stream
def register_callback_for_skeleton_stream(self, callback: Callable[[SkeletonData], None])Register a callback invoked when the skeleton data is updated.
Exceptions raised by the callback are logged to the contactglovesdk
logger and do not prevent other callbacks from being invoked.
Parameters
callbackCallback function to register.
register_callback_for_raw_skeleton_stream
def register_callback_for_raw_skeleton_stream(self, callback: Callable[[RawSkeletonData], None])Register a callback invoked when the pre-retarget skeleton is updated.
Exceptions raised by the callback are logged to the contactglovesdk
logger and do not prevent other callbacks from being invoked.
register_callback_for_rawsensor_stream
def register_callback_for_rawsensor_stream(self, callback: Callable[[RawSensorData], None])Register a callback invoked when the raw sensor Transform data is updated.
Exceptions raised by the callback are logged to the contactglovesdk
logger and do not prevent other callbacks from being invoked.
Parameters
callbackCallback function to register.
register_callback_for_retarget_profile_info_stream
def register_callback_for_retarget_profile_info_stream(self, callback: Callable[[RetargetProfileInfo], None])Register a callback that receives the retarget profile information response.
Exceptions raised by the callback are logged to the contactglovesdk
logger and do not prevent other callbacks from being invoked.
DEFAULT_DS_PORT
DEFAULT_DS_PORT: int = 25791Default OSC receive port number on the DivingStation side
Host
from contactglovesdk import HostData class holding the host information of DivingStation
Passed to connect_to_host() / disconnect(). The receive port on the
SDK (local) side is managed by ContactGloveClient, so it is not part of
this class.
Public Attributes
| Type | Name | Description |
|---|---|---|
str | host_name | Host name (for example "localhost") |
str | ip_address | IP address (for example "127.0.0.1") |
int | port | OSC receive port number on the DivingStation side |
Host.host_name
host_name: strHost name (for example "localhost")
Host.ip_address
ip_address: strIP address (for example "127.0.0.1")
Host.port
port: int = 25791OSC receive port number on the DivingStation side
GloveData
from contactglovesdk import GloveDataData class holding the information of a glove device
Corresponds to the data received from the OSC address /DS2/HC/Device.
Record layout (10 fields per device):
string id, string pair_id,
int battery_percentage, int is_haptics, int is_left,
int device_type, int color, int connected_state,
string name, int is_external_power_presentPublic Attributes
| Type | Name | Description |
|---|---|---|
str | id | Device ID |
str | pair_id | ID of the paired glove (an empty string if there is none) |
int | battery_percentage | Remaining battery level [0 - 100]. -1 means an invalid value |
bool | is_haptics | Whether the haptics feature is present |
bool | is_left | Whether this is a left-hand glove |
DeviceFamilyType | device_type | Kind of device |
DeviceColor | color | Device display-color setting |
DeviceConnectedState | connected_state | Connection state |
str | name | Device name |
bool | is_external_power_present | Whether external power is detected |
GloveData.id
id: str = ""Device ID
GloveData.pair_id
pair_id: str = ""ID of the paired glove (an empty string if there is none)
GloveData.battery_percentage
battery_percentage: int = -1Remaining battery level [0 - 100]. -1 means an invalid value
GloveData.is_haptics
is_haptics: bool = FalseWhether the haptics feature is present
GloveData.is_left
is_left: bool = FalseWhether this is a left-hand glove
GloveData.device_type
device_type: DeviceFamilyType = DeviceFamilyType.ContactGloveKind of device
GloveData.color
color: DeviceColor = DeviceColor.AchromaticDevice display-color setting
GloveData.connected_state
connected_state: DeviceConnectedState = DeviceConnectedState.UnknownConnection state
GloveData.name
name: str = ""Device name
GloveData.is_external_power_present
is_external_power_present: bool = FalseWhether external power is detected
ControllerData
from contactglovesdk import ControllerDataData class holding the input state of the controller
Corresponds to the data received from the OSC address /DS2/HC/Controller.
Record layout (15 fields per controller):
string id, int is_left,
int a, int b, int sys,
int trigger_button, int joystick_button, int trackpad_button,
float trigger, float grip_value, float grip_force,
float joystick_x, float joystick_y,
float trackpad_x, float trackpad_yPublic Attributes
| Type | Name | Description |
|---|---|---|
str | id | Glove ID |
bool | is_left | Whether this is the left hand |
ButtonStatus | a_button | Press state of the A button |
ButtonStatus | b_button | Press state of the B button |
ButtonStatus | sys_button | Press state of the system button |
ButtonStatus | trigger_button | Press state of the trigger button |
ButtonStatus | joystick_button | Press state of the joystick button |
ButtonStatus | trackpad_button | Press state of the trackpad touch |
float | trigger | Trigger value (0.0 to 1.0) |
float | grip_value | Grip value (0.0 to 1.0) |
float | grip_force | Grip force (0.0 to 1.0) |
float | joystick_x | Joystick X axis value (-1.0 to 1.0) |
float | joystick_y | Joystick Y axis value (-1.0 to 1.0) |
float | trackpad_x | Trackpad X axis value (-1.0 to 1.0) |
float | trackpad_y | Trackpad Y axis value (-1.0 to 1.0) |
ControllerData.id
id: str = ""Glove ID
ControllerData.is_left
is_left: bool = FalseWhether this is the left hand
ControllerData.a_button
a_button: ButtonStatus = ButtonStatus.UnpressedPress state of the A button
ControllerData.b_button
b_button: ButtonStatus = ButtonStatus.UnpressedPress state of the B button
ControllerData.sys_button
sys_button: ButtonStatus = ButtonStatus.UnpressedPress state of the system button
ControllerData.trigger_button
trigger_button: ButtonStatus = ButtonStatus.UnpressedPress state of the trigger button
ControllerData.joystick_button
joystick_button: ButtonStatus = ButtonStatus.UnpressedPress state of the joystick button
ControllerData.trackpad_button
trackpad_button: ButtonStatus = ButtonStatus.UnpressedPress state of the trackpad touch
ControllerData.trigger
trigger: float = 0.0Trigger value (0.0 to 1.0)
ControllerData.grip_value
grip_value: float = 0.0Grip value (0.0 to 1.0)
ControllerData.grip_force
grip_force: float = 0.0Grip force (0.0 to 1.0)
ControllerData.joystick_x
joystick_x: float = 0.0Joystick X axis value (-1.0 to 1.0)
ControllerData.joystick_y
joystick_y: float = 0.0Joystick Y axis value (-1.0 to 1.0)
ControllerData.trackpad_x
trackpad_x: float = 0.0Trackpad X axis value (-1.0 to 1.0)
ControllerData.trackpad_y
trackpad_y: float = 0.0Trackpad Y axis value (-1.0 to 1.0)
ErgonomicsData
from contactglovesdk import ErgonomicsDataData class holding the finger opening and bending angle data
Corresponds to the data received from the OSC address /DS2/HC/Ergonomics.
Record layout (25 fields per hand):
string id, int is_left,
int generated_at_ms_hi, int generated_at_ms_lo, int tracking_state,
float[20] valuesvalues[i] corresponds to ErgonomicsIndex(i).
Angles are in degrees, and a bending angle is 0 degrees when the finger
is extended.
Public Attributes
| Type | Name | Description |
|---|---|---|
str | id | Glove ID |
bool | is_left | Whether this is the left hand |
int | timestamp_ms | Time at which the frame was generated (Unix time, milliseconds) |
TrackingState | tracking_state | IK-derived tracking state |
list[float] | values | Opening and bending angle value per joint (20 elements per hand, degrees) |
ErgonomicsData.id
id: str = ""Glove ID
ErgonomicsData.is_left
is_left: bool = FalseWhether this is the left hand
ErgonomicsData.timestamp_ms
timestamp_ms: int = 0Time at which the frame was generated (Unix time, milliseconds)
ErgonomicsData.tracking_state
tracking_state: TrackingState = TrackingState.TrackedIK-derived tracking state
ErgonomicsData.values
values: list[float] = [0.0, ...] # 20 elementsOpening and bending angle value per joint (20 elements per hand, degrees)
SkeletonData
from contactglovesdk import SkeletonDataData class holding the hand skeleton data (joint positions and rotations)
Corresponds to the data received from the OSC address /DS2/HC/HandSkeleton.
Record layout (one record per message, 157 fields):
string id, string profile_uuid, int is_left,
int generated_at_ms_hi, int generated_at_ms_lo, int tracking_state,
float[75] # 25 nodes × (p_x, p_y, p_z)
float[76] # 19 nodes × (q_w, q_x, q_y, q_z)positions[i] corresponds to SkeletonNode(i) (25 elements).
rotations[i] corresponds to SkeletonRotationNode(i) (19 elements; the
wrist and the 5 fingertip nodes are excluded).
Positions are in meters and are expressed in model-rooted space (the coordinate system whose origin is the wrist). Rotations are local quaternions relative to the parent node.
Public Attributes
| Type | Name | Description |
|---|---|---|
str | id | Glove ID |
str | profile_uuid | Fixed UUID of the retarget profile |
bool | is_left | Whether this is the left hand |
int | timestamp_ms | Time at which the frame was generated (Unix time, milliseconds) |
TrackingState | tracking_state | Tracking state derived from the retarget IK |
list[Vec3] | positions | Position per node (25 elements). See SkeletonNode for the indices |
list[Quaternion] | rotations | Rotation per node (19 elements). See SkeletonRotationNode for the indices |
SkeletonData.id
id: str = ""Glove ID
SkeletonData.profile_uuid
profile_uuid: str = ""Fixed UUID of the retarget profile
SkeletonData.is_left
is_left: bool = FalseWhether this is the left hand
SkeletonData.timestamp_ms
timestamp_ms: int = 0Time at which the frame was generated (Unix time, milliseconds)
SkeletonData.tracking_state
tracking_state: TrackingState = TrackingState.TrackedTracking state derived from the retarget IK
SkeletonData.positions
positions: list[Vec3] = [Vec3(x=0.0, y=0.0, z=0.0), ...] # 25 elementsPosition per node (25 elements). See SkeletonNode for the indices
SkeletonData.rotations
rotations: list[Quaternion] = [Quaternion(w=1.0, x=0.0, y=0.0, z=0.0), ...] # 19 elementsRotation per node (19 elements). See SkeletonRotationNode for the indices
RawSkeletonData
from contactglovesdk import RawSkeletonDataData class holding the hand skeleton data before retargeting.
Corresponds to the data received from the OSC address
/DS2/HC/HandSkeletonRaw. There is one record per message, and it has the
same position and rotation layout as SkeletonData except for
profile_uuid.
Public Attributes
| Type | Name | Description |
|---|---|---|
str | id | Glove ID |
bool | is_left | Whether this is the left hand |
int | timestamp_ms | Time at which the frame was generated (Unix time, milliseconds) |
TrackingState | tracking_state | Tracking state derived from the IK of the source skeleton |
list[Vec3] | positions | Position per node (25 elements). See SkeletonNode for the indices |
list[Quaternion] | rotations | Rotation per node (19 elements). See SkeletonRotationNode for the indices |
RawSkeletonData.id
id: str = ""Glove ID
RawSkeletonData.is_left
is_left: bool = FalseWhether this is the left hand
RawSkeletonData.timestamp_ms
timestamp_ms: int = 0Time at which the frame was generated (Unix time, milliseconds)
RawSkeletonData.tracking_state
tracking_state: TrackingState = TrackingState.TrackedTracking state derived from the IK of the source skeleton
RawSkeletonData.positions
positions: list[Vec3] = [Vec3(x=0.0, y=0.0, z=0.0), ...] # 25 elementsPosition per node (25 elements). See SkeletonNode for the indices
RawSkeletonData.rotations
rotations: list[Quaternion] = [Quaternion(w=1.0, x=0.0, y=0.0, z=0.0), ...] # 19 elementsRotation per node (19 elements). See SkeletonRotationNode for the indices
RawSensorData
from contactglovesdk import RawSensorDataData class holding the raw sensor Transform data for one hand
Corresponds to the data received from the OSC address
/DS2/HC/RawSensorTransforms. Each Transform is expressed in the same
right-handed model-rooted space as /DS2/HC/HandSkeleton. The position is
the sensor center position with the wrist as the origin, and the
rotation is the orientation from the sensor local frame to model-rooted
space.
Record layout (39 fields per hand):
string id, int is_left,
int generated_at_ms_hi, int generated_at_ms_lo,
float[35] # 5 sensors × (p_x, p_y, p_z, q_w, q_x, q_y, q_z)transforms[i] corresponds to RawSensorIndex(i) (5 elements, in the
order thumb, index finger, middle finger, ring finger, little finger).
Public Attributes
| Type | Name | Description |
|---|---|---|
str | id | Glove ID |
bool | is_left | Whether this is the left hand |
int | timestamp_ms | Time at which the frame was generated (Unix time, milliseconds) |
list[Transform] | transforms | Position and rotation per sensor (5 elements per hand). See RawSensorIndex for the indices |
RawSensorData.id
id: str = ""Glove ID
RawSensorData.is_left
is_left: bool = FalseWhether this is the left hand
RawSensorData.timestamp_ms
timestamp_ms: int = 0Time at which the frame was generated (Unix time, milliseconds)
RawSensorData.transforms
transforms: list[Transform] = [Transform(position=Vec3(x=0.0, y=0.0, z=0.0), rotation=Quaternion(w=1.0, x=0.0, y=0.0, z=0.0)), ...] # 5 elementsPosition and rotation per sensor (5 elements per hand). See RawSensorIndex for the indices
RetargetProfileInfo
from contactglovesdk import RetargetProfileInfoData class holding the response that carries retarget profile information.
Corresponds to the data received from the OSC address
/DS2/HC/HandSkeleton/Profile.
status is 0 (present), 1 (the UUID is valid but no such profile exists)
or 2 (malformed query).
Public Attributes
| Type | Name | Description |
|---|---|---|
int | request_id | Client-supplied value that correlates a request with its response |
str | profile_uuid | Retarget profile UUID, depending on the status |
int | status | Result of retrieving the profile information (0, 1, 2) |
str | name | User-facing profile name |
str | description | Description of the profile |
RetargetProfileInfo.request_id
request_id: int = 0Client-supplied value that correlates a request with its response
RetargetProfileInfo.profile_uuid
profile_uuid: str = ""Retarget profile UUID, depending on the status
RetargetProfileInfo.status
status: int = 0Result of retrieving the profile information (0, 1, 2)
RetargetProfileInfo.name
name: str = ""User-facing profile name
RetargetProfileInfo.description
description: str = ""Description of the profile
Transform
from contactglovesdk import TransformTransform combining a position and a rotation
Used as each element of RawSensorData.transforms.
Public Attributes
Transform.position
position: Vec3 = Vec3(x=0.0, y=0.0, z=0.0)Position
Transform.rotation
rotation: Quaternion = Quaternion(w=1.0, x=0.0, y=0.0, z=0.0)Rotation
Vec3
from contactglovesdk import Vec3Three-dimensional vector
Public Attributes
Vec3.x
x: float = 0.0X component
Vec3.y
y: float = 0.0Y component
Vec3.z
z: float = 0.0Z component
Quaternion
from contactglovesdk import QuaternionQuaternion representing a rotation
Public Attributes
Quaternion.w
w: float = 1.0Scalar component
Quaternion.x
x: float = 0.0X component
Quaternion.y
y: float = 0.0Y component
Quaternion.z
z: float = 0.0Z component
ContactGloveSDKError
from contactglovesdk import ContactGloveSDKErrorclass ContactGloveSDKError(Exception)Base class for the exceptions raised by the SDK
SDKNotAvailableError
from contactglovesdk import SDKNotAvailableErrorclass SDKNotAvailableError(ContactGloveSDKError)Raised when opening a local UDP socket fails (for example because the port is in use)
NotConnectedError
from contactglovesdk import NotConnectedErrorclass NotConnectedError(ContactGloveSDKError)Raised when an operation that requires a connection is attempted while that connection does not exist
InvalidIDError
from contactglovesdk import InvalidIDErrorclass InvalidIDError(ContactGloveSDKError)Raised when no data for the specified glove ID exists in the current data store