This release is a pre-release and may not be stable for production use.
hex_dora_node_teleop
Dora nodes for reading teleoperation inputs from keyboard and joystick/gamepad using evdev. Each node maintains an internal state table updated by background threads and outputs the full state at the configured tick rate (recommended 100 Hz).
Nodes
| Node | Description | Inputs | Outputs |
|---|---|---|---|
hex-dora-teleop-keyboard |
Keyboard letter-key state reader | tick |
keys |
hex-dora-teleop-joystick |
Joystick/Gamepad button & axis state reader | tick |
buttons, axes |
hex-dora-teleop-test-keyboard |
Terminal viewer for keyboard state | tick, keys |
- |
hex-dora-teleop-test-joystick |
Terminal viewer for joystick state | tick, buttons, axes |
- |
Prerequisites
Accessing /dev/input/* requires the current user to be in the input group:
sudo usermod -aG input $USER
# Log out and back in for the change to take effect
Installation
pip install hex_dora_node_teleop
YAML Examples
Keyboard (100 Hz)
nodes:
- id: teleop_keyboard
build: pip install hex_dora_node_teleop
path: hex-dora-teleop-keyboard
inputs:
tick: dora/timer/millis/10
outputs:
- keys
env:
NODE_NAME: teleop_keyboard
DEVICE_PATH: "" # auto-detect; or set e.g. /dev/input/event0
- id: test_keyboard
build: pip install hex_dora_node_teleop
path: hex-dora-teleop-test-keyboard
inputs:
tick: dora/timer/millis/10
keys: teleop_keyboard/keys
env:
NODE_NAME: test_keyboard
Joystick / Gamepad (100 Hz)
nodes:
- id: teleop_joystick
build: pip install hex_dora_node_teleop
path: hex-dora-teleop-joystick
inputs:
tick: dora/timer/millis/10
outputs:
- buttons
- axes
env:
NODE_NAME: teleop_joystick
DEVICE_PATH: "" # auto-detect; or set e.g. /dev/input/event5
- id: test_joystick
build: pip install hex_dora_node_teleop
path: hex-dora-teleop-test-joystick
inputs:
tick: dora/timer/millis/10
buttons: teleop_joystick/buttons
axes: teleop_joystick/axes
env:
NODE_NAME: test_joystick
Inputs
Teleop Nodes (keyboard / joystick)
| Input | Type | Description |
|---|---|---|
tick |
dora/timer/millis/* |
Timer tick to trigger state output (use millis/10 for 100 Hz) |
Test Nodes (test-keyboard)
| Input | Type | Description |
|---|---|---|
tick |
dora/timer/millis/* |
Timer tick to refresh terminal display |
keys |
Arrow UInt8Array | Keyboard letter-key state from keyboard node |
Test Nodes (test-joystick)
| Input | Type | Description |
|---|---|---|
tick |
dora/timer/millis/* |
Timer tick to refresh terminal display |
buttons |
Arrow UInt8Array | Button states from joystick node |
axes |
Arrow Float64Array | Axis values from joystick node |
Outputs
keys (keyboard)
Arrow UInt8Array of length 26 — one element per letter key (a–z, in order). 1 = pressed, 0 = released.
state_data: UInt8Array # pa.array([0, 0, 1, ...], type=pa.uint8())
metadata = {
"keys": "a,b,c,...,z", # comma-separated key names
"primitive": "keyboard_state",
}
buttons (joystick)
Arrow UInt8Array — one element per detected gamepad button. 1 = pressed, 0 = released. Button list is auto-detected from device capabilities.
buttons_data: UInt8Array # pa.array([0, 1, 0, ...], type=pa.uint8())
metadata = {
"names": "BTN_SOUTH,BTN_EAST,...", # comma-separated button names
"primitive": "joystick_buttons",
}
axes (joystick)
Arrow Float64Array — one element per detected analog axis, normalized to [-1.0, 1.0]. Axis list is auto-detected from device capabilities.
axes_data: Float64Array # pa.array([-0.5, 0.0, ...], type=pa.float64())
metadata = {
"names": "ABS_X,ABS_Y,...", # comma-separated axis names
"primitive": "joystick_axes",
}
Environment Variables
All Nodes
| Variable | Type | Default | Description |
|---|---|---|---|
NODE_NAME |
str |
"" |
Dora node name passed to Node() constructor; empty = use default |
Keyboard Node
| Variable | Type | Default | Description |
|---|---|---|---|
DEVICE_PATH |
str |
"" (auto) |
Specific /dev/input/eventN path; empty = auto-detect all keyboards |
Joystick Node
| Variable | Type | Default | Description |
|---|---|---|---|
DEVICE_PATH |
str |
"" (auto) |
Specific /dev/input/eventN path; empty = auto-detect first joystick |
Architecture
Both keyboard and joystick nodes follow the same pattern:
- Device discovery — enumerate
/dev/input/*viaevdev.list_devices()and filter by capabilities (letter keys for keyboard, analog axes for joystick). - Background reader thread — a daemon thread continuously reads
evdevevents and updates an in-memory state table protected by athreading.Lock. - Dora tick loop — on each
tickinput, the node snapshots the current state table and sends it as an Arrow array output.
This decouples the variable-rate hardware events from the fixed-rate dora output, ensuring consistent 100 Hz state updates regardless of actual input event frequency.
License
This project is licensed under Apache-2.0.
Metadata
Release files for hex-dora-node-teleop 0.0.1a4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| hex_dora_node_teleop-0.0.1a4.tar.gz | 12.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| hex_dora_node_teleop-0.0.1a4-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 25.5 kB
Release files / hex_dora_node_teleop-0.0.1a4.tar.gz
| Download URL | hex_dora_node_teleop-0.0.1a4.tar.gz |
|---|---|
| Size | 12.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d71e4347be199f55d78313f1fb0fd994b6661c71c6036f16fd9c0325a92ddcd1
|
|
BLAKE2b-256 checksum How to use checksums |
a4068414323298b26258034c1c56b42a53e42cb21271eb69d722a757feed218b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.10.12
|
Release files / hex_dora_node_teleop-0.0.1a4-py3-none-any.whl
| Download URL | hex_dora_node_teleop-0.0.1a4-py3-none-any.whl |
|---|---|
| Size | 13.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
709fc534bc16fc5871523f1887968cf137ccfeacb8d2545433c8248369f8773d
|
|
BLAKE2b-256 checksum How to use checksums |
2019eb28b3b83c4012559fd81927cbea469fb081bedd33a9aefdbdba56d97b73
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.10.12
|