Docs FTC Integration

HardwareActions

The facade over the hardware thread — run, call, callAsync, bulkRead.

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:

MethodBlocks caller?ReturnsUse for
run(action)novoidfire-and-forget hardware writes
call(action)yesthe valuereads you need now
callAsync(action)noCompletableFuture<T>reads you’ll consume later
bulkRead(hz, reader)noBulkReadHandleperiodic 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 a hardware = true loop, an @OnHardwareThread subscriber, or a bulk-read reader, call(...) blocks the single hardware thread on a task it can never start — the robot hangs. There, use device.raw() and touch the device directly. call(...) is safe from onSafeLoop, 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

MethodPurpose
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