Dora Node for Teleoperation Input (Keyboard & Joystick)
Project description
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 |
state |
hex-dora-teleop-joystick |
Joystick/Gamepad button & axis state reader | tick |
buttons, axes |
hex-dora-teleop-test-keyboard |
Terminal viewer for keyboard state | tick, state |
- |
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:
- state
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
state: teleop_keyboard/state
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 |
state |
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
state (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.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hex_dora_node_teleop-0.0.1a1.tar.gz.
File metadata
- Download URL: hex_dora_node_teleop-0.0.1a1.tar.gz
- Upload date:
- Size: 12.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fbd2c3200fc7dbfb2cf85a7de7e667e98c97353e99da72f480dd10621aaa66b5
|
|
| MD5 |
f202ecc5e5b1df790f62c7f8e506f26f
|
|
| BLAKE2b-256 |
7503bb73b96cb1c052e8c0110e01e967ed069c6a7c528de834fd8a89f022075d
|
File details
Details for the file hex_dora_node_teleop-0.0.1a1-py3-none-any.whl.
File metadata
- Download URL: hex_dora_node_teleop-0.0.1a1-py3-none-any.whl
- Upload date:
- Size: 13.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3a037308a59352f1a287d5f8bb2556200151155842f02f748c56cf462d591e00
|
|
| MD5 |
78705ba19baf443756ea174afce63f42
|
|
| BLAKE2b-256 |
2c491d2636060de43784975490f550c851ab26e8b8d5a0ab405febf625063830
|