src.utils.device_runtime package

Submodules

src.utils.device_runtime.devices module

class src.utils.device_runtime.devices.DeviceState(clutch_button=False, gripper_button=False, button=False, position=<factory>, joints=<factory>, gimbals=<factory>, force=<factory>)[source]

Bases: object

Shared mutable state updated by the haptic-device scheduler callback.

All fields are written from the haptics scheduler thread and read from the main rendering thread; no explicit locking is provided — callers rely on Python’s GIL for atomicity on individual attribute reads.

clutch_button

True while the clutch (Button 1) is held down.

gripper_button

True while the gripper (Button 2) is held down.

button

Convenience alias for clutch_button.

position

Current stylus tip position [x, y, z] in device space (metres).

joints

6-element joint angle list in the order [q0, q1, q2_corrected, gimbal0, gimbal1, gimbal2] (radians).

gimbals

Raw gimbal angle list as read from the device.

force

Force command [fx, fy, fz] (newtons) sent to the device on each scheduler tick.

button: bool = False
clutch_button: bool = False
force: list[float]
gimbals: list[float]
gripper_button: bool = False
joints: list[float]
position: list[float]
src.utils.device_runtime.devices.make_state_callback(device_state, joint2_coeff)[source]

Build the haptic-device scheduler callback that populates device_state.

The callback is designed to be called by the OpenHaptics scheduler at a fixed servo rate (typically 1 kHz). It performs three tasks:

  1. Reads raw joint and gimbal angles and assembles the corrected 6-DOF joint vector with the joint-2 parallelogram correction:

    \[q_2^{\text{corr}} = q_2^{\text{raw}} - c_{J2} \cdot q_1\]

    where \(c_{J2}\) is joint2_coeff.

  2. Sends the current force command back to the device via set_force().

  3. Updates the button flags from the device button bitmask.

Parameters:
  • device_state (DeviceState) – Shared DeviceState object to update.

  • joint2_coeff (float) – Parallelogram coupling coefficient for joint 2.

Returns:

Zero-argument callable suitable for HapticDevice.

src.utils.device_runtime.devices.setup_device(device_state, device_name, joint2_coeff)[source]

Create and initialise a single HapticDevice.

Parameters:
  • device_state (DeviceState) – DeviceState that the callback will update.

  • device_name (str) – OpenHaptics device name string (e.g. 'Default PHANToM').

  • joint2_coeff (float) – Parallelogram coupling coefficient for joint 2.

Return type:

HapticDevice

Returns:

Initialised HapticDevice.

src.utils.device_runtime.devices.setup_devices(left_state, right_state, left_device_name, right_device_name, left_joint2_coeff, right_joint2_coeff)[source]

Create and initialise a matched left/right pair of haptic devices.

Parameters:
  • left_state (DeviceState) – DeviceState for the left device.

  • right_state (DeviceState) – DeviceState for the right device.

  • left_device_name (str) – OpenHaptics device name for the left device.

  • right_device_name (str) – OpenHaptics device name for the right device.

  • left_joint2_coeff (float) – Joint-2 correction coefficient for the left device.

  • right_joint2_coeff (float) – Joint-2 correction coefficient for the right device.

Return type:

tuple[HapticDevice, HapticDevice]

Returns:

(left_device, right_device) — each an initialised HapticDevice.

src.utils.device_runtime.devices.state_to_q(phantom, state)[source]

Convert a DeviceState joint list to a Phantom joint vector.

Copies min(phantom.dof, len(state.joints)) values from state.joints into a zero-initialised (dof,) float array.

Parameters:
Return type:

ndarray

Returns:

(dof,) float64 joint vector.

src.utils.device_runtime.runners module

src.utils.device_runtime.runners.run_with_dual_devices(*, left_state, right_state, callback)[source]

Set up a left/right pair of haptic devices and run the teleoperation loop.

Reads device names and joint-2 coefficients for both sides from settings.py, constructs both devices, starts the scheduler, calls callback, then shuts down cleanly.

Parameters:
Return type:

None

src.utils.device_runtime.runners.run_with_single_device(*, device_state, side, callback)[source]

Set up a single haptic device and run the teleoperation loop.

Reads device name and joint-2 coefficient from settings.py based on side, constructs the HapticDevice, starts the scheduler, calls callback, then shuts down cleanly.

Parameters:
  • device_state (DeviceState) – DeviceState to be updated by the device callback.

  • side (Literal['left', 'right']) – 'left' or 'right' — selects device name and J2 coefficient from settings.

  • callback (Callable[[], None]) – Main teleoperation loop (runs between scheduler start/stop).

Return type:

None

Module contents

class src.utils.device_runtime.DeviceState(clutch_button=False, gripper_button=False, button=False, position=<factory>, joints=<factory>, gimbals=<factory>, force=<factory>)[source]

Bases: object

Shared mutable state updated by the haptic-device scheduler callback.

All fields are written from the haptics scheduler thread and read from the main rendering thread; no explicit locking is provided — callers rely on Python’s GIL for atomicity on individual attribute reads.

clutch_button

True while the clutch (Button 1) is held down.

gripper_button

True while the gripper (Button 2) is held down.

button

Convenience alias for clutch_button.

position

Current stylus tip position [x, y, z] in device space (metres).

joints

6-element joint angle list in the order [q0, q1, q2_corrected, gimbal0, gimbal1, gimbal2] (radians).

gimbals

Raw gimbal angle list as read from the device.

force

Force command [fx, fy, fz] (newtons) sent to the device on each scheduler tick.

button: bool = False
clutch_button: bool = False
force: list[float]
gimbals: list[float]
gripper_button: bool = False
joints: list[float]
position: list[float]
src.utils.device_runtime.make_state_callback(device_state, joint2_coeff)[source]

Build the haptic-device scheduler callback that populates device_state.

The callback is designed to be called by the OpenHaptics scheduler at a fixed servo rate (typically 1 kHz). It performs three tasks:

  1. Reads raw joint and gimbal angles and assembles the corrected 6-DOF joint vector with the joint-2 parallelogram correction:

    \[q_2^{\text{corr}} = q_2^{\text{raw}} - c_{J2} \cdot q_1\]

    where \(c_{J2}\) is joint2_coeff.

  2. Sends the current force command back to the device via set_force().

  3. Updates the button flags from the device button bitmask.

Parameters:
  • device_state (DeviceState) – Shared DeviceState object to update.

  • joint2_coeff (float) – Parallelogram coupling coefficient for joint 2.

Returns:

Zero-argument callable suitable for HapticDevice.

src.utils.device_runtime.run_with_dual_devices(*, left_state, right_state, callback)[source]

Set up a left/right pair of haptic devices and run the teleoperation loop.

Reads device names and joint-2 coefficients for both sides from settings.py, constructs both devices, starts the scheduler, calls callback, then shuts down cleanly.

Parameters:
Return type:

None

src.utils.device_runtime.run_with_single_device(*, device_state, side, callback)[source]

Set up a single haptic device and run the teleoperation loop.

Reads device name and joint-2 coefficient from settings.py based on side, constructs the HapticDevice, starts the scheduler, calls callback, then shuts down cleanly.

Parameters:
  • device_state (DeviceState) – DeviceState to be updated by the device callback.

  • side (Literal['left', 'right']) – 'left' or 'right' — selects device name and J2 coefficient from settings.

  • callback (Callable[[], None]) – Main teleoperation loop (runs between scheduler start/stop).

Return type:

None

src.utils.device_runtime.setup_device(device_state, device_name, joint2_coeff)[source]

Create and initialise a single HapticDevice.

Parameters:
  • device_state (DeviceState) – DeviceState that the callback will update.

  • device_name (str) – OpenHaptics device name string (e.g. 'Default PHANToM').

  • joint2_coeff (float) – Parallelogram coupling coefficient for joint 2.

Return type:

HapticDevice

Returns:

Initialised HapticDevice.

src.utils.device_runtime.setup_devices(left_state, right_state, left_device_name, right_device_name, left_joint2_coeff, right_joint2_coeff)[source]

Create and initialise a matched left/right pair of haptic devices.

Parameters:
  • left_state (DeviceState) – DeviceState for the left device.

  • right_state (DeviceState) – DeviceState for the right device.

  • left_device_name (str) – OpenHaptics device name for the left device.

  • right_device_name (str) – OpenHaptics device name for the right device.

  • left_joint2_coeff (float) – Joint-2 correction coefficient for the left device.

  • right_joint2_coeff (float) – Joint-2 correction coefficient for the right device.

Return type:

tuple[HapticDevice, HapticDevice]

Returns:

(left_device, right_device) — each an initialised HapticDevice.

src.utils.device_runtime.state_to_q(phantom, state)[source]

Convert a DeviceState joint list to a Phantom joint vector.

Copies min(phantom.dof, len(state.joints)) values from state.joints into a zero-initialised (dof,) float array.

Parameters:
Return type:

ndarray

Returns:

(dof,) float64 joint vector.