Input Event

Shipping
input_event

Human/Hardware-in-the-loop input: keyboard/mouse drives a live scalar into a running simulation

Signature

Outputs

  • valueScalarThe current input level (a Scalar with optional unit; exact — control input carries no uncertainty).

Parameters

KeyTypeDefaultNotes
sourceenumkeyone of: key, mouse_button, mouse_x, mouse_y, mouse_wheel
bindingtextSpaceThe bound key (e.g. Space, W, ArrowUp) or mouse button (Left / Right / Middle). Shown only for key / mouse_button sources. Capture it in the Sim Input panel while live.
modeenumholdone of: hold, toggle, impulse, axis
value_onfloat1.0(unit)Output while pressed / toggled-on, or the value the axis maps to at its maximum.
value_offfloat0.0(unit)Resting output (released / toggled-off), or the value the axis maps to at its minimum. The batch/head-less run emits this.
impulse_msfloat50.0msHow long (in wall-clock ms) an Impulse pulse holds the On value before returning to Off. Active only in Impulse mode.
valuefloat0.0(unit)The current output level. Driven by the bound input while live (see the Sim Input panel); editable directly as the rest value.
unittextPhysical unit of the emitted value (e.g. N, V, rad). Dimensionless when empty.

Description

Input Event is a runtime Human/Hardware-in-the-loop (HIL / HumanIL) input source. Drop it inside a execution_mode = Simulation compound, wire its value output into the dynamics, and while the sim runs live (wall-clock-paced "Run Live") the user's keyboard / mouse drives its output in real time — pressing a key fires a thruster, holding a button opens a valve, a mouse axis steers a setpoint. It lets a person (or, later, a piece of hardware) sit inside the control loop and react to the evolving state.

The Rust builtin itself does zero math: it is a runtime-tunable constant scalar source — exactly like constant, it emits the value parameter on its single output. All the input interpretation — which key, hold vs. toggle vs. impulse vs. axis, the high/low levels — lives on the Dart side (SimInputController). When an input event occurs the UI resolves a numeric and writes it straight into the running solver via exec_set_live_param(node, "value", v) — the same zero-recompile slot write a slider drag uses. So the node stays trivial and deterministic: it only ever emits whatever scalar currently sits in value (its rest level in batch / before the first event), exact and unitful.

Because the live retune overwrites value each event, this node is whitelisted alongside constant in the AOT tunable-slot gate, so even a compiled scalar program can be driven live; on the generic evaluator path (a model with events / forcing inputs) the value write is re-read every step for free.

Outside a live simulation — on a batch Run or the acyclic dataflow path — it is a plain constant source emitting value (which defaults to the configured value_off rest level), so a model authored with input events still runs head-less and reproducibly.

Modes: Hold is momentary (on while pressed), Toggle flips on each press, Impulse emits one short impulse_ms pulse per press, and Axis maps a continuous device value between value_off and value_on. The binding and mode params apply only to the button-style sources (key / mouse_button); the axis sources are inherently continuous and hide them.

Mathematics

Examples

Thruster on the space bar

Set source = key, binding = Space, mode = hold, value_on = 1, value_off = 0, unit = N. Wire value into a force input. While the sim runs live, holding Space applies ; releasing returns to . A batch run emits the rest value the whole time.

Steering a setpoint with the mouse

Set source = mouse_x, mode = axis. The continuous mouse-X position maps between value_off (at minimum) and value_on (at maximum), driving a live setpoint into the controller as you move the cursor.

Impulse valve kick

Set mode = impulse, impulse_ms = 50. Each key press holds value_on for of wall-clock time, then falls back to value_off — a one-shot kick regardless of how long the key is held.

Applications

  • Human-in-the-loop control: piloting a simulated vehicle, spacecraft, or robot from the keyboard/mouse while the physics runs live.
  • Interactive what-if probing — nudging a setpoint or disturbance mid-run to feel how a controller responds.
  • Teaching / demo scenarios where a person injects thruster fires, valve openings, or steering inputs into a running model.
  • A tunable live constant that a batch run reproducibly pins to its rest level for head-less, deterministic replay.

Neat

The Rust core is deliberately math-free: it is the exact same constant-from-param source as `constant`, with all device interpretation pushed to Dart — so the solver stays deterministic and the node is trivially reproducible head-less.

The live driver reuses the *slider-drag* mechanism: an input event is just `exec_set_live_param(node, "value", v)`, a zero-recompile slot write, so keyboard/mouse control needs no graph recompile per event.

It is whitelisted next to `constant` in the AOT tunable-slot gate, so even an ahead-of-time-compiled scalar program can be driven live without falling back to the generic evaluator.

The same node degrades to a plain constant on a batch run, so a model authored for interactive HIL still executes reproducibly and head-less.

Known issues

Live driving only happens under wall-clock-paced "Run Live" inside a Simulation compound; on a batch run or the dataflow path it is a static constant at its rest level.

A bypassed ("muted") or unwired Input Event drives nothing in the running solver — the HUD dims the input lamp rather than raising an error, so a mis-authored node can silently do nothing.

Modes, bindings, and axis mapping live entirely on the Dart side; the Rust builtin surfaces only the resolved `value`, so the input semantics are not visible from the core alone.

See also

control-flowinputhilhuman-in-the-looplivesimulationkeyboardmousesource