The AutoDsl Builder¶
AutoDsl (in com.vcs.valleylib.core.auto) is a small, declarative builder for autonomous routines. It produces a single SequentialCommandGroup under the hood, but reads like a script:
Command auto = AutoDsl.auto(a -> a
.run(claw::close)
.waitSeconds(0.2)
.command(driveToBackdrop)
.either(vision::seesLeft, scoreLeft, scoreCenter)
.parallel(park, retractLift)
);
Because the result is just a Command, you can schedule it, decorate it (auto.withTimeout(28)), or nest it inside other groups.
For Pedro Pathing autos, prefer the drive-aware PedroAutoDsl, which adds follow(...) and waitUntilDriveIdle() steps.
Builder methods¶
Each method appends one step to the sequence and returns the builder for chaining.
Adding commands and actions¶
| Method | Step added |
|---|---|
command(cmd) |
Runs the command |
add(cmd) |
Alias for command (for teams used to add-step DSLs) |
run(action) |
Runs a Runnable once (InstantCommand) |
doInstant(action) |
Alias for run |
Timing¶
| Method | Step added |
|---|---|
waitSeconds(seconds) |
Pause for a duration |
waitFor(seconds) |
Alias for waitSeconds |
Conditionals¶
| Method | Step added |
|---|---|
when(condition, cmd) |
Runs cmd only if condition is true when the step starts (skipped otherwise) |
either(condition, onTrue, onFalse) |
if/else between two commands |
ifElse(condition, onTrue, onFalse) |
Alias for either |
Concurrency¶
| Method | Step added |
|---|---|
parallel(cmds...) |
All commands together; step ends when all finish |
race(cmds...) |
All commands together; step ends when any finishes |
deadline(deadline, others...) |
Step ends when the deadline command finishes |
Instrumentation¶
| Method | Step added |
|---|---|
marker(label, sink) |
Emits a label to a callback — great for telemetry timelines and profiling |
AutoDsl.auto(a -> a
.marker("start", tag -> telemetryBus.put("auto", tag))
.command(driveOut)
.marker("driven", tag -> telemetryBus.put("auto", tag))
);
Building¶
build() finalizes the sequence — but you rarely call it yourself; AutoDsl.auto(block) calls it for you and returns the finished command.
A complete example¶
Command auto = AutoDsl.auto(a -> a
.marker("start", tag -> telemetryBus.put("auto", tag))
.command(intake.runOnce(intake::closeGate))
.waitSeconds(0.15)
.either(
vision::seesPropLeft,
drive.follow(leftPath),
drive.follow(centerPath)
)
.deadline(
drive.follow(backdropPath),
shooter.run(shooter::spin).withTimeout(1.2)
)
.when(sensor::isReady, outtake.runOnce(outtake::drop))
);
Migration-friendly aliases¶
The alias methods (add, doInstant, waitFor, ifElse) exist so routines written against other command DSLs port over with minimal renaming. They are exact synonyms — use whichever vocabulary your team prefers, but be consistent.
AutoDsl vs. plain composition¶
There is nothing AutoDsl does that Commands.sequence(...) + decorators cannot. Choose AutoDsl when:
- the routine is long and linear (auto periods usually are),
- you want newcomers to read the routine top-to-bottom,
- you want timeline markers for debugging.
Stick with plain composition for short snippets and button bindings.
Loops and branches? Use a state machine
AutoDsl is deliberately linear. When a routine needs to loop (cycle until the clock runs out), branch and rejoin, retry, or honor overrides from any step, build it as a StateMachine command instead — each state can still use drive.follow(...) and any other command.