Development guide
Adding new features
- Create a new branch from
masterwith a descriptive name. - Implement your feature.
- Create a pull request to
masterand assign a reviewer. - The reviewer will review your code and merge it into
master.
Adding a new device
This section describes how to add support for a new SpaceMouse or similar 6-DOF device.
1. Find Device IDs
First, identify your device's Vendor ID (VID) and Product ID (PID).
Linux/macOS:
lsusb
# Example output: Bus 001 Device 013: ID 256f:c652 3Dconnexion Universal Receiver
# VID = 256f, PID = c652
Using hidapitester:
./hidapitester --list
# Example: 046D/C626: 3Dconnexion - SpaceNavigator
2. Analyze HID Data
Use hidapitester to read raw data from your device:
./hidapitester --vidpid <VID/PID> --open --read-input
Move the SpaceMouse knob in each direction and identify which bytes change:
- Channel 1: Usually translation data (X, Y, Z)
- Channel 2: Usually rotation data (pitch, roll, yaw)
- Channel 3: Button data
Each axis is typically a signed 16-bit value (2 bytes, little-endian).
3. Add Device to devices.toml
Edit pyspacemouse/devices.toml and add your device:
[YourDeviceName]
hid_id = [0xVID, 0xPID] # Vendor ID and Product ID in hex
led_id = [0x04, 0x01] # Optional: [report_id, on_value] for LED control
axis_scale = 350.0 # Scaling factor (adjust based on device sensitivity)
# Axis mappings: [channel, byte1, byte2, scale]
# - channel: HID report number (1, 2, or 3)
# - byte1, byte2: Byte positions for the 16-bit value
# - scale: 1 for normal, -1 for inverted axis
mappings.x = [1, 1, 2, 1]
mappings.y = [1, 3, 4, -1]
mappings.z = [1, 5, 6, -1]
mappings.pitch = [2, 1, 2, -1]
mappings.roll = [2, 3, 4, -1]
mappings.yaw = [2, 5, 6, 1]
# Button mappings: [channel, byte, bit]
[YourDeviceName.buttons]
LEFT = [3, 1, 0] # Channel 3, byte 1, bit 0
RIGHT = [3, 1, 1] # Channel 3, byte 1, bit 1
Mapping format explained:
| Field | Description |
|---|---|
channel |
HID report ID (first byte of each HID message) |
byte1, byte2 |
Byte positions within the report (1-indexed) |
scale |
Sign modifier: 1 = normal, -1 = inverted |
bit |
For buttons: which bit in the byte (0-7) |
4. Test Your Configuration
import pyspacemouse
# Check if device is recognized
devices = pyspacemouse.get_connected_devices()
print(devices) # Should show your device name
# Test reading
with pyspacemouse.open() as device:
while True:
state = device.read()
print(f"X:{state.x:.2f} Y:{state.y:.2f} Z:{state.z:.2f}")
print(f"Roll:{state.roll:.2f} Pitch:{state.pitch:.2f} Yaw:{state.yaw:.2f}")
print(f"Buttons: {state.buttons}")
5. Fine-tune Axis Directions
If an axis moves in the wrong direction, change its scale from 1 to -1 or vice versa in devices.toml.
6. Submit a Pull Request
Once your device works correctly:
- Create a branch:
git checkout -b add-device-<name> - Add your device entry to
devices.toml - Test thoroughly with the examples in
examples/ - Submit a PR with your device name and any notes about testing
Using Custom Configuration (Without Modifying Library)
If you don't want to modify the library, use create_device_info():
import pyspacemouse
device_spec = pyspacemouse.create_device_info({
"name": "MyCustomDevice",
"hid_id": [0x256F, 0xC652],
"axis_scale": 350.0,
"mappings": {
"x": [1, 1, 2, 1],
"y": [1, 3, 4, -1],
"z": [1, 5, 6, -1],
"pitch": [2, 1, 2, -1],
"roll": [2, 3, 4, -1],
"yaw": [2, 5, 6, 1],
},
"buttons": {
"LEFT": [3, 1, 0],
"RIGHT": [3, 1, 1],
},
})
with pyspacemouse.open(device_spec=device_spec) as device:
state = device.read()
See Custom Device Configuration for more details.
How to write documentation
To install the required dependencies, run pip install pyspacemouse[docs].
Edit README.md only in the root folder. The documentation is automatically generated from README.md and docs/ folder.
To update documentation from root to /docs use macro make fixRelativeLinkDocs which will replace all relative links from / to /docs folder.
Building the documentation
The documentation is built using mkdocs. To test the documentation locally, run make docs-serve and open http://localhost:8000 in your browser.
Deploying the documentation
The documentation is deployed automatically using GitHub Actions. Just push to the master branch and the documentation will be updated automatically.