Input Messages

Human input device types for teleoperation and manual control.

# simplified
from horus import JoystickInput, KeyboardInput

JoystickInput

Event-based joystick/gamepad input. Each message represents a single input event (button press, axis move, hat change, or connection event) rather than the full controller state.

Constructor

# simplified
joy = JoystickInput(joystick_id=0, element_id=0, value=0.0, pressed=False)

Fields

FieldTypeAccessDescription
joystick_idintgetController ID
element_idintgetButton/axis/hat element ID
valuefloatget/setAxis value (-1.0 to 1.0) or hat value
pressedboolgetWhether a button is pressed
event_typestrgetEvent type: "button", "axis", "hat", or "connection"
element_namestrgetHuman-readable element name
timestamp_msintgetEvent timestamp in milliseconds

Static Methods (Factory Constructors)

MethodReturnsDescription
JoystickInput.new_button(joystick_id, button_id, name, pressed)JoystickInputCreate a button event
JoystickInput.new_axis(joystick_id, axis_id, name, value)JoystickInputCreate an axis event
JoystickInput.new_hat(joystick_id, hat_id, name, value)JoystickInputCreate a hat/d-pad event
JoystickInput.new_connection(joystick_id, connected)JoystickInputCreate a connection/disconnection event

Methods

MethodReturnsDescription
is_button()boolTrue if this is a button event
is_axis()boolTrue if this is an axis event
is_hat()boolTrue if this is a hat/d-pad event
is_connection_event()boolTrue if this is a connection event
is_connected()boolTrue if the joystick just connected (only valid for connection events)

Example

# simplified
# Create events using factory methods
btn = JoystickInput.new_button(joystick_id=0, button_id=0, name="A", pressed=True)
axis = JoystickInput.new_axis(joystick_id=0, axis_id=1, name="LeftY", value=0.75)

# Query event type
if btn.is_button() and btn.pressed:
    print(f"Button {btn.element_name} pressed")

if axis.is_axis():
    print(f"Axis {axis.element_name} = {axis.value}")

KeyboardInput

Keyboard key event with modifier support.

Constructor

# simplified
key = KeyboardInput(key_name="", code=0, pressed=True, modifiers=0)

Fields

FieldTypeAccessDescription
key_namestrgetHuman-readable key name
codeintgetNumeric key code
pressedboolgetWhether the key is pressed
modifier_flagsintgetBitmask of active modifiers
timestamp_msintgetEvent timestamp in milliseconds

Methods

MethodReturnsDescription
is_ctrl()boolTrue if Ctrl modifier is active
is_shift()boolTrue if Shift modifier is active
is_alt()boolTrue if Alt modifier is active

Example

# simplified
key = KeyboardInput(key_name="w", code=119, pressed=True)
if key.pressed and key.is_ctrl():
    print("Ctrl+W pressed")

Example: Joystick Teleoperation

# simplified
import horus

linear_speed = 0.0
angular_speed = 0.0

def teleop_tick(node):
    global linear_speed, angular_speed

    joy = node.recv("joystick")
    if joy is None:
        return

    # Handle axis events for driving
    if joy.is_axis():
        if joy.element_name == "LeftY":
            linear_speed = joy.value if abs(joy.value) > 0.1 else 0.0
        elif joy.element_name == "LeftX":
            angular_speed = joy.value * 2.0 if abs(joy.value) > 0.1 else 0.0

    # E-stop on button A
    if joy.is_button() and joy.element_name == "A" and joy.pressed:
        linear_speed = 0.0
        angular_speed = 0.0

    cmd = horus.CmdVel(linear=linear_speed, angular=angular_speed)
    node.send("cmd_vel", cmd)

AudioFrame

Audio data for speech recognition, sound localization, and audio processing.

Constructor

# simplified
frame = AudioFrame(sample_rate=16000, channels=1, samples=None, timestamp_ns=0, frame_id="")

Fields

FieldTypeAccessDescription
sampleslist[float]getAudio sample data (f32)
num_samplesintgetNumber of valid samples
sample_rateintgetSample rate in Hz
channelsintgetNumber of audio channels
duration_msfloatgetFrame duration in milliseconds
frame_countintgetNumber of frames (samples / channels)
timestamp_nsintget/setTimestamp in nanoseconds
frame_idstrgetSource identifier

Static Methods

MethodReturnsDescription
AudioFrame.mono(sample_rate, samples)AudioFrameCreate mono (1-channel) frame
AudioFrame.stereo(sample_rate, samples)AudioFrameCreate stereo (2-channel) frame
AudioFrame.multi_channel(sample_rate, channels, samples)AudioFrameCreate multi-channel frame

Example

# simplified
# Mono audio at 16kHz
frame = AudioFrame.mono(16000, samples=[0.0] * 1600)
print(f"Duration: {frame.duration_ms:.1f}ms")  # 100.0ms

# Stereo audio at 44.1kHz
stereo = AudioFrame.stereo(44100, samples=[0.0] * 88200)

See Also