A Python library for interfacing with the 3D Systems Phantom Omni haptic device on Windows.
Communicates over FireWire (PCIe 1394 card) using the OpenHaptics HDAPI via ctypes — no ROS required.
| Requirement | Details |
|---|---|
| OS | Windows 10 (x64) |
| Hardware | PCIe FireWire card (tested with Digitus DS-30201-5 3+1) |
| Device drivers | Phantom Device Driver v5.1.7 (FireWire/Parallel) |
| SDK | OpenHaptics Developer Edition v3.4.0 |
| Python | 3.x |
Note: The Phantom Omni is a 20+ year old device. Setting it up requires legacy FireWire drivers and the OpenHaptics SDK.
Download: All required drivers (FireWire legacy driver, Phantom Device Driver) and the OpenHaptics SDK are bundled together in the GitHub Releases of this repository for convenience.
Windows 8 and later ship without the legacy 1394 OHCI driver that the Phantom Omni requires.
- Download the legacy driver from Microsoft Support for your architecture (x64 or x86).
- Install
Legacy1394.inf. The driver files are typically located at:
C:\Program Files (x86)\1394 OHCI Compliant Host Controller (Legacy)\x64_driver - A community guide for Windows 8/10 is available here.
Download and install Phantom Device Driver v5.1.7 for FireWire/Parallel devices from 3D Systems Support.
The full installation guide (PDF) is available here.
Download OpenHaptics_Developer_Edition_v3.4.0.zip from:
After installation, make sure the OpenHaptics bin directory (containing HD.dll) is on your system PATH, or copy HD.dll to C:\Windows\System32.
This library uses only the Python standard library (ctypes, os, sys, time). No additional packages are required.
Before running any Python code, you can verify the device is working correctly using the Phantom Test and Phantom Configuration GUI tools that are installed alongside the Phantom Device Driver. These allow you to test connectivity, calibration, and force feedback without writing any code.
Clone or download this repository, then run the included test script:
python test.pyThis initialises the device and continuously prints the end-effector position and velocity to the console. Press Ctrl+C to stop.
For a minimal custom script:
import time
from phantom import PhantomOmni
omni = PhantomOmni()
try:
for _ in range(100):
state = omni.get_state()
print("Position:", state["position"])
time.sleep(0.1)
finally:
omni.close()The diagram below shows the coordinate system and joint axes used by the Phantom Omni. The origin is at the base of the device.
| Axis | Description |
|---|---|
| X | Points to the right (from the device's perspective) |
| Y | Points upward |
| Z | Points toward the user |
Joint angles are reported as [waist, shoulder, elbow] in radians. Gimbal angles are reported as [yaw, pitch, roll] in radians.
Note: Only
get_position()andget_velocity()(viaget_state()) have been fully tested and confirmed working on hardware. Other API calls — including gimbal angles, joint torques, and force output — are implemented based on the OpenHaptics HDAPI specification but have not been fully verified on this specific device setup. Use them with caution.
Initialises the device. Pass None to connect to the default device.
Returns a dictionary with the full device state:
position— Cartesian position[x, y, z]in mmvelocity— Cartesian velocity[x, y, z]in mm/sjoint_angles— Waist, shoulder, elbow angles in radiansgimbal_angles— Yaw, pitch, roll angles in radiansbuttons— Button bitmask (integer)
Returns [x, y, z] position in mm.
Returns [x, y, z] velocity in mm/s.
Returns [yaw, pitch, roll] in radians.
Returns {"button1": bool, "button2": bool} for the stylus buttons.
Sends a force command to the device in Newtons.
Stops the scheduler and releases the device. Always call this (or use try/finally) when finished.
See LICENSE for details.

