HardwareActions
HardwareActions is the facade over the orchestrator’s single hardware thread. Get it from SafeOpMode (the hardware field) or from any orchestrator: orchestrator.hardware().
Four methods, four use cases:
| Method | Blocks caller? | Returns | Use for |
|---|---|---|---|
run(action) | no | void | fire-and-forget hardware writes |
call(action) | yes | the value | reads you need now |
callAsync(action) | no | CompletableFuture<T> | reads you’ll consume later |
bulkRead(hz, reader) | no | BulkReadHandle | periodic sensor sampling |
run — async write
hardware.run(() -> motor.setPower(0.5));
Submits and returns immediately. The action executes on the hardware thread in submission order relative to all other hardware work.
call — synchronous read
int pos = hardware.call(() -> motor.getCurrentPosition());
Blocks the caller until the hardware thread finishes and returns the value. Exceptions thrown by the callable are unwrapped and rethrown on the caller’s thread. An overload accepts (timeout, unit) and throws TimeoutException if the hardware thread doesn’t answer in time.
Deadlock: never
call(...)from hardware-thread code. Inside ahardware = trueloop, an@OnHardwareThreadsubscriber, or a bulk-read reader,call(...)blocks the single hardware thread on a task it can never start — the robot hangs. There, usedevice.raw()and touch the device directly.call(...)is safe fromonSafeLoop,onSafeInit, plain subscribers, and actions.
callAsync — future read
CompletableFuture<Double> amps = hardware.callAsync(() -> motor.getCurrent(CurrentUnit.AMPS));
amps.thenAccept(a -> orchestrator.publish("motor/amps", a));
Same routing as call, but non-blocking and safe to call from the hardware thread itself.
bulkRead — periodic sensor sampling
hardware.bulkRead(50, view -> {
// runs on the hardware thread at 50 Hz
double amps = motor.getCurrent(CurrentUnit.AMPS);
view.publish("motor/amps", amps);
});
Schedules the BulkReader on the hardware thread at the given rate. The reader receives a HardwareView with publish(topic, value) and getLatestValue(topic, type). Returns a BulkReadHandle; call hardware.stopBulkRead(handle) to cancel.
Diagnostics
| Method | Purpose |
|---|---|
isHardwareThread() | true if the current thread is the hardware thread |
assertNotHardwareThread() | throws IllegalStateException if it is — called for you in SafeOpMode.loop() |
tick() | reserved hook, currently a no-op; SafeOpMode.loop() calls it |
shutdown() | closes the entire orchestrator, not just hardware access — you rarely need this, since SafeOpMode.stop() closes everything |
Next steps
- SafeDevice — per-device wrappers over this facade.
@OnHardwareThread— the annotation path to the same thread.