Gray Matter LogoGray Matter Workshop

Mechanisms

KEY CONCEPT

Mechanisms with WPILib Commands V3

A mechanism models one physical part of the robot: an arm, a flywheel, the drivetrain. In Commands V3, Mechanism is a base class you extend. It gives you factory methods (run(), runRepeatedly(), idle()) that hand you a Command builder you can name, schedule, or compose.

One class per physical thing, hardware as private fields, configuration in the constructor. Default behavior comes from an automatic idle() default (override it with setDefaultCommand) rather than a periodic() override, and the WPILib compiler plugin enforces .named(...) on every command at build time; forget it and the project won't compile.

↳ TAKEAWAY

One mechanism per physical thing. The base class gives you Command factories; you give it your hardware and the per-command behavior.

Anatomy of a Mechanism

A v3 mechanism is a regular Java class that extends Mechanism. Hardware lives in private fields, configuration happens in the constructor, and every public method that callers will schedule returns a Commandbuilt from one of the base class's factory methods.

The factory methods you'll actually use

The Mechanismbase class provides three built-in factories that cover most of the commands you'll write. Each returns a builder; chain .named("...") to finish it.

ONCE THEN HOLD

mech.run(coroutine -> { ... })

Runs the lambda once. If the body uses coroutine.yield(), waitUntil(...), or await(...), the command stays scheduled until the body falls off. Most teaching examples use this.

run(coroutine -> { ... }).named("...")
EVERY TICK

mech.runRepeatedly(runnable)

Calls the runnable every scheduler tick (20 ms) for as long as the command is scheduled. This is the v3 spelling of "put it in periodic()", but it's scoped to a command instead of always-on.

runRepeatedly(this::tick).named(...)
DO NOTHING

mech.idle()

Returns a ready-made command that yields forever at LOWEST_PRIORITY. Every mechanism already has this wired as its default — set your own default to override.

setDefaultCommand(idle())
NOTE · NAMING IS ENFORCED

.named(...) is a compile-time requirement

Both run(...) and runRepeatedly(...) hand back a staged builder, not a finished Command. A WPILib compiler plugin watches for that builder escaping a method without a matching .named(...) call and turns it into a build error, so every command shows up in telemetry under a name you actually chose.

Default commands and idle behavior

Every mechanism has a default command. The scheduler runs it whenever no higher-priority command requires that mechanism, and pre-empts it the moment one does. Out of the box, the default is idle() — a no-op park at LOWEST_PRIORITY — so a fresh mechanism just sits there safely. Call setDefaultCommand(...)to override it. A default that needs no controller (like hold-in-place) can be set right in the mechanism's constructor; a default that depends on a joystick is set from the Teleop OpModeinstead, because the mechanism's constructor has no controller (see the Triggers page).

A second example: leader/follower flywheel

Multi-motor mechanisms follow the same shape. The Phoenix 6 follower control still lives in the constructor, the per-command behavior still comes from run(...), and reads stay as plain getters.

Physical hardware vs. code example

The workshop's flywheel mechanism only has one physical motor. The follower wiring above is included to show the multi-motor pattern. If you're running this on the workshop hardware, either drop the follower lines or add a second physical motor.
NOTE · API STATUS

This is the WPILib 2027 alpha

Commands V3 — including the Mechanism base class, the builder-chain factories, and the compile-time .named(...) enforcement — run on Java 25 and deploy to SystemCore. The stack is the WPILib 2027 alpha (GradleRIO 2027.0.0-alpha-6).
CHECKPOINT · 5 ITEMS