mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-19 00:41:43 +00:00
[cmd3] Change Command.noRequirements to accept a command implementation (#8783)
This is more ergonomic than `Command.noRequirements().executing(...)`
This commit is contained in:
@@ -85,7 +85,7 @@ import org.wpilib.units.measure.Time;
|
||||
* // to run when not in use. Interrupting one of the inner commands while it's
|
||||
* // running will cancel the entire sequence.
|
||||
* private Command advancedScoringSequence() {
|
||||
* return Command.noRequirements().executing(coroutine -> {
|
||||
* return Command.noRequirements(coroutine -> {
|
||||
* coroutine.await(drivetrain.driveToScoringLocation());
|
||||
* coroutine.await(elevator.moveToScoringHeight());
|
||||
* coroutine.await(gripper.release());
|
||||
@@ -226,15 +226,17 @@ public interface Command {
|
||||
* Creates a command that does not require any hardware; that is, it does not affect the state of
|
||||
* any physical objects. This is useful for commands that do some cleanup or state management,
|
||||
* such as resetting odometry or sensors, that you don't want to interrupt a command that's
|
||||
* controlling the mechanisms it affects.
|
||||
* controlling the mechanisms it affects, or for a command composition that you don't want to
|
||||
* inherit the requirements of its child commands.
|
||||
*
|
||||
* <p>More configuration options are needed after calling this function before the command can be
|
||||
* created. See {@link StagedCommandBuilder} for details.
|
||||
*
|
||||
* @param body The command's body. Cannot be null.
|
||||
* @return a builder that can be used to configure the resulting command
|
||||
*/
|
||||
static NeedsExecutionBuilderStage noRequirements() {
|
||||
return new StagedCommandBuilder().noRequirements();
|
||||
static NeedsNameBuilderStage noRequirements(Consumer<Coroutine> body) {
|
||||
return new StagedCommandBuilder().noRequirements().executing(body);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -326,7 +328,7 @@ public interface Command {
|
||||
static NeedsNameBuilderStage waitUntil(BooleanSupplier condition) {
|
||||
requireNonNullParam(condition, "condition", "Command.waitUntil");
|
||||
|
||||
return noRequirements().executing(coroutine -> coroutine.waitUntil(condition));
|
||||
return noRequirements(coroutine -> coroutine.waitUntil(condition));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -339,7 +341,7 @@ public interface Command {
|
||||
static NeedsNameBuilderStage waitFor(Time duration) {
|
||||
requireNonNullParam(duration, "duration", "Command.waitFor");
|
||||
|
||||
return noRequirements().executing(coroutine -> coroutine.wait(duration));
|
||||
return noRequirements(coroutine -> coroutine.wait(duration));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -79,7 +79,7 @@ public final class Coroutine {
|
||||
*
|
||||
* <pre>{@code
|
||||
* Command example() {
|
||||
* return Command.noRequirements().executing(coroutine -> {
|
||||
* return Command.noRequirements(coroutine -> {
|
||||
* Command child = ...;
|
||||
* coroutine.fork(child);
|
||||
* // ... do more things
|
||||
@@ -121,7 +121,7 @@ public final class Coroutine {
|
||||
*
|
||||
* <pre>{@code
|
||||
* Command example() {
|
||||
* return Command.noRequirements().executing(coroutine -> {
|
||||
* return Command.noRequirements(coroutine -> {
|
||||
* Collection<Command> innerCommands = ...;
|
||||
* coroutine.fork(innerCommands);
|
||||
* // ... do more things
|
||||
|
||||
@@ -34,7 +34,7 @@ import org.wpilib.units.measure.Time;
|
||||
* canceled when the enclosing command exits.
|
||||
*
|
||||
* <pre>{@code
|
||||
* Command shootWhileAiming = Command.noRequirements().executing(co -> {
|
||||
* Command shootWhileAiming = Command.noRequirements(co -> {
|
||||
* turret.atTarget.onTrue(shooter.shootOnce());
|
||||
* co.await(turret.lockOnGoal());
|
||||
* }).named("Shoot While Aiming");
|
||||
|
||||
@@ -27,8 +27,7 @@ class BindingScopeTest extends SchedulerTest {
|
||||
BindingScope[] scopeRef = new BindingScope[1];
|
||||
|
||||
var command =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
coroutine -> {
|
||||
BindingScope scope = BindingScope.createNarrowestScope(m_scheduler);
|
||||
scopeRef[0] = scope;
|
||||
@@ -49,8 +48,7 @@ class BindingScopeTest extends SchedulerTest {
|
||||
|
||||
BindingScope[] scopeRef = new BindingScope[1];
|
||||
var command =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
coroutine -> {
|
||||
BindingScope scope = BindingScope.createNarrowestScope(m_scheduler);
|
||||
scopeRef[0] = scope;
|
||||
|
||||
@@ -24,8 +24,7 @@ class CoroutineTest extends CommandTestBase {
|
||||
var c = new NullCommand();
|
||||
|
||||
var all =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
co -> {
|
||||
co.fork(a, b, c);
|
||||
co.park();
|
||||
@@ -45,8 +44,7 @@ class CoroutineTest extends CommandTestBase {
|
||||
AtomicInteger i = new AtomicInteger(0);
|
||||
|
||||
var yieldInSynchronized =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
co -> {
|
||||
while (true) {
|
||||
synchronized (mutex) {
|
||||
@@ -68,8 +66,7 @@ class CoroutineTest extends CommandTestBase {
|
||||
AtomicInteger i = new AtomicInteger(0);
|
||||
|
||||
var yieldInLock =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
co -> {
|
||||
while (true) {
|
||||
lock.lock();
|
||||
@@ -93,8 +90,7 @@ class CoroutineTest extends CommandTestBase {
|
||||
AtomicReference<Runnable> escapeeCallback = new AtomicReference<>();
|
||||
|
||||
var badCommand =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
co -> {
|
||||
escapeeCallback.set(co::yield);
|
||||
})
|
||||
@@ -111,12 +107,10 @@ class CoroutineTest extends CommandTestBase {
|
||||
@SuppressWarnings("CoroutineMayNotBeInScope")
|
||||
void usingParentCoroutineInChildThrows() {
|
||||
var parent =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
parentCoroutine -> {
|
||||
parentCoroutine.await(
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
childCoroutine -> {
|
||||
parentCoroutine.yield();
|
||||
})
|
||||
@@ -135,10 +129,9 @@ class CoroutineTest extends CommandTestBase {
|
||||
AtomicBoolean secondRan = new AtomicBoolean(false);
|
||||
AtomicBoolean ranAfterAwait = new AtomicBoolean(false);
|
||||
|
||||
var firstInner = Command.noRequirements().executing(c2 -> firstRan.set(true)).named("First");
|
||||
var firstInner = Command.noRequirements(c2 -> firstRan.set(true)).named("First");
|
||||
var secondInner =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
c2 -> {
|
||||
secondRan.set(true);
|
||||
c2.park();
|
||||
@@ -146,8 +139,7 @@ class CoroutineTest extends CommandTestBase {
|
||||
.named("Second");
|
||||
|
||||
var outer =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
co -> {
|
||||
co.awaitAny(firstInner, secondInner);
|
||||
|
||||
|
||||
@@ -26,8 +26,8 @@ class ParallelGroupBuilderTest {
|
||||
|
||||
@Test
|
||||
void optionalPopulatesOptionalOnly() {
|
||||
var a = Command.noRequirements().executing(Coroutine::park).named("A");
|
||||
var b = Command.noRequirements().executing(Coroutine::park).named("B");
|
||||
var a = Command.noRequirements(Coroutine::park).named("A");
|
||||
var b = Command.noRequirements(Coroutine::park).named("B");
|
||||
|
||||
var group = new ParallelGroupBuilder().optional(a, b).withAutomaticName();
|
||||
|
||||
@@ -50,8 +50,8 @@ class ParallelGroupBuilderTest {
|
||||
|
||||
@Test
|
||||
void requiringPopulatesRequiredOnly() {
|
||||
var a = Command.noRequirements().executing(Coroutine::park).named("A");
|
||||
var b = Command.noRequirements().executing(Coroutine::park).named("B");
|
||||
var a = Command.noRequirements(Coroutine::park).named("A");
|
||||
var b = Command.noRequirements(Coroutine::park).named("B");
|
||||
|
||||
var group = new ParallelGroupBuilder().requiring(a, b).withAutomaticName();
|
||||
|
||||
@@ -62,10 +62,10 @@ class ParallelGroupBuilderTest {
|
||||
|
||||
@Test
|
||||
void mixedRequiredAndOptional() {
|
||||
var reqA = Command.noRequirements().executing(Coroutine::park).named("ReqA");
|
||||
var reqB = Command.noRequirements().executing(Coroutine::park).named("ReqB");
|
||||
var optX = Command.noRequirements().executing(Coroutine::park).named("OptX");
|
||||
var optY = Command.noRequirements().executing(Coroutine::park).named("OptY");
|
||||
var reqA = Command.noRequirements(Coroutine::park).named("ReqA");
|
||||
var reqB = Command.noRequirements(Coroutine::park).named("ReqB");
|
||||
var optX = Command.noRequirements(Coroutine::park).named("OptX");
|
||||
var optY = Command.noRequirements(Coroutine::park).named("OptY");
|
||||
|
||||
var group =
|
||||
new ParallelGroupBuilder().requiring(reqA, reqB).optional(optX, optY).withAutomaticName();
|
||||
|
||||
@@ -183,9 +183,9 @@ class ParallelGroupTest extends CommandTestBase {
|
||||
|
||||
@Test
|
||||
void automaticNameRace() {
|
||||
var a = Command.noRequirements().executing(coroutine -> {}).named("A");
|
||||
var b = Command.noRequirements().executing(coroutine -> {}).named("B");
|
||||
var c = Command.noRequirements().executing(coroutine -> {}).named("C");
|
||||
var a = Command.noRequirements(coroutine -> {}).named("A");
|
||||
var b = Command.noRequirements(coroutine -> {}).named("B");
|
||||
var c = Command.noRequirements(coroutine -> {}).named("C");
|
||||
|
||||
var group = new ParallelGroupBuilder().optional(a, b, c).withAutomaticName();
|
||||
assertEquals("(A | B | C)", group.name());
|
||||
@@ -193,9 +193,9 @@ class ParallelGroupTest extends CommandTestBase {
|
||||
|
||||
@Test
|
||||
void automaticNameAll() {
|
||||
var a = Command.noRequirements().executing(coroutine -> {}).named("A");
|
||||
var b = Command.noRequirements().executing(coroutine -> {}).named("B");
|
||||
var c = Command.noRequirements().executing(coroutine -> {}).named("C");
|
||||
var a = Command.noRequirements(coroutine -> {}).named("A");
|
||||
var b = Command.noRequirements(coroutine -> {}).named("B");
|
||||
var c = Command.noRequirements(coroutine -> {}).named("C");
|
||||
|
||||
var group = new ParallelGroupBuilder().requiring(a, b, c).withAutomaticName();
|
||||
assertEquals("(A & B & C)", group.name());
|
||||
@@ -203,9 +203,9 @@ class ParallelGroupTest extends CommandTestBase {
|
||||
|
||||
@Test
|
||||
void automaticNameDeadline() {
|
||||
var a = Command.noRequirements().executing(coroutine -> {}).named("A");
|
||||
var b = Command.noRequirements().executing(coroutine -> {}).named("B");
|
||||
var c = Command.noRequirements().executing(coroutine -> {}).named("C");
|
||||
var a = Command.noRequirements(coroutine -> {}).named("A");
|
||||
var b = Command.noRequirements(coroutine -> {}).named("B");
|
||||
var c = Command.noRequirements(coroutine -> {}).named("C");
|
||||
|
||||
var group = new ParallelGroupBuilder().requiring(a).optional(b, c).withAutomaticName();
|
||||
assertEquals("[(A) * (B | C)]", group.name());
|
||||
|
||||
@@ -84,7 +84,7 @@ class SchedulerCancellationTests extends CommandTestBase {
|
||||
|
||||
@Test
|
||||
void cancelsEvictsOnDeck() {
|
||||
var command = Command.noRequirements().executing(Coroutine::park).named("Command");
|
||||
var command = Command.noRequirements(Coroutine::park).named("Command");
|
||||
m_scheduler.schedule(command);
|
||||
m_scheduler.cancel(command);
|
||||
assertFalse(m_scheduler.isScheduledOrRunning(command));
|
||||
@@ -95,8 +95,7 @@ class SchedulerCancellationTests extends CommandTestBase {
|
||||
var ranAfterCancel = new AtomicBoolean(false);
|
||||
var commandRef = new AtomicReference<Command>(null);
|
||||
var command =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
co -> {
|
||||
co.scheduler().cancel(commandRef.get());
|
||||
ranAfterCancel.set(true);
|
||||
@@ -115,7 +114,7 @@ class SchedulerCancellationTests extends CommandTestBase {
|
||||
|
||||
@Test
|
||||
void cancelAllEvictsOnDeck() {
|
||||
var command = Command.noRequirements().executing(Coroutine::park).named("Command");
|
||||
var command = Command.noRequirements(Coroutine::park).named("Command");
|
||||
m_scheduler.schedule(command);
|
||||
m_scheduler.cancelAll();
|
||||
assertFalse(m_scheduler.isScheduledOrRunning(command));
|
||||
@@ -125,7 +124,7 @@ class SchedulerCancellationTests extends CommandTestBase {
|
||||
void cancelAllCancelsAll() {
|
||||
var commands = new ArrayList<Command>(10);
|
||||
for (int i = 1; i <= 10; i++) {
|
||||
commands.add(Command.noRequirements().executing(Coroutine::yield).named("Command " + i));
|
||||
commands.add(Command.noRequirements(Coroutine::yield).named("Command " + i));
|
||||
}
|
||||
commands.forEach(m_scheduler::schedule);
|
||||
m_scheduler.run();
|
||||
@@ -141,8 +140,7 @@ class SchedulerCancellationTests extends CommandTestBase {
|
||||
void cancelAllCallsOnCancelHookForRunningCommands() {
|
||||
AtomicBoolean ranHook = new AtomicBoolean(false);
|
||||
var command =
|
||||
Command.noRequirements()
|
||||
.executing(Coroutine::park)
|
||||
Command.noRequirements(Coroutine::park)
|
||||
.whenCanceled(() -> ranHook.set(true))
|
||||
.named("Command");
|
||||
m_scheduler.schedule(command);
|
||||
@@ -155,8 +153,7 @@ class SchedulerCancellationTests extends CommandTestBase {
|
||||
void cancelAllDoesNotCallOnCancelHookForQueuedCommands() {
|
||||
AtomicBoolean ranHook = new AtomicBoolean(false);
|
||||
var command =
|
||||
Command.noRequirements()
|
||||
.executing(Coroutine::park)
|
||||
Command.noRequirements(Coroutine::park)
|
||||
.whenCanceled(() -> ranHook.set(true))
|
||||
.named("Command");
|
||||
m_scheduler.schedule(command);
|
||||
@@ -209,20 +206,16 @@ class SchedulerCancellationTests extends CommandTestBase {
|
||||
@Test
|
||||
void cancelDeeplyNestedCompositions() {
|
||||
Command root =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
co -> {
|
||||
co.await(
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
co2 -> {
|
||||
co2.await(
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
co3 -> {
|
||||
co3.await(
|
||||
Command.noRequirements()
|
||||
.executing(Coroutine::park)
|
||||
Command.noRequirements(Coroutine::park)
|
||||
.named("Park"));
|
||||
})
|
||||
.named("C3"));
|
||||
|
||||
@@ -20,8 +20,7 @@ class SchedulerConflictTests extends CommandTestBase {
|
||||
var mech = new Mechanism("The Mechanism", m_scheduler);
|
||||
|
||||
var group =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
co -> {
|
||||
co.awaitAll(
|
||||
mech.run(Coroutine::park).named("First"),
|
||||
@@ -64,8 +63,7 @@ class SchedulerConflictTests extends CommandTestBase {
|
||||
.named("Second");
|
||||
|
||||
var group =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
co -> {
|
||||
co.fork(first);
|
||||
co.fork(second);
|
||||
@@ -88,25 +86,21 @@ class SchedulerConflictTests extends CommandTestBase {
|
||||
void nestedOneShotCompositionsAllRunInOneCycle() {
|
||||
var runs = new AtomicInteger(0);
|
||||
Supplier<Command> makeOneShot =
|
||||
() -> Command.noRequirements().executing(_c -> runs.incrementAndGet()).named("One Shot");
|
||||
() -> Command.noRequirements(_c -> runs.incrementAndGet()).named("One Shot");
|
||||
var command =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
co -> {
|
||||
co.fork(makeOneShot.get());
|
||||
co.fork(makeOneShot.get());
|
||||
co.fork(
|
||||
Command.noRequirements()
|
||||
.executing(inner -> inner.fork(makeOneShot.get()))
|
||||
Command.noRequirements(inner -> inner.fork(makeOneShot.get()))
|
||||
.named("Inner"));
|
||||
co.fork(
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
co2 -> {
|
||||
co2.fork(makeOneShot.get());
|
||||
co2.fork(
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
co3 -> {
|
||||
co3.fork(makeOneShot.get());
|
||||
})
|
||||
@@ -130,7 +124,7 @@ class SchedulerConflictTests extends CommandTestBase {
|
||||
// Child conflicts with and is lower priority than the Top command
|
||||
// It should not be scheduled, and the parent command should exit immediately
|
||||
var child = mechanism.run(Coroutine::park).named("Child");
|
||||
var parent = Command.noRequirements().executing(co -> co.await(child)).named("Parent");
|
||||
var parent = Command.noRequirements(co -> co.await(child)).named("Parent");
|
||||
|
||||
m_scheduler.schedule(top);
|
||||
m_scheduler.schedule(parent);
|
||||
@@ -149,7 +143,7 @@ class SchedulerConflictTests extends CommandTestBase {
|
||||
// Child conflicts with and is higher priority than the Top command
|
||||
// It should be scheduled, and the top command should be interrupted
|
||||
var child = mechanism.run(Coroutine::park).named("Child");
|
||||
var parent = Command.noRequirements().executing(co -> co.await(child)).named("Parent");
|
||||
var parent = Command.noRequirements(co -> co.await(child)).named("Parent");
|
||||
|
||||
m_scheduler.schedule(top);
|
||||
m_scheduler.schedule(parent);
|
||||
|
||||
@@ -64,8 +64,7 @@ class SchedulerDefaultCommandTests extends CommandTestBase {
|
||||
var commandScopedCommand = mech.run(Coroutine::park).named("Command-Scoped Default Command");
|
||||
|
||||
var scopingCommand =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
co -> {
|
||||
mech.setDefaultCommand(commandScopedCommand);
|
||||
co.park();
|
||||
@@ -93,8 +92,7 @@ class SchedulerDefaultCommandTests extends CommandTestBase {
|
||||
|
||||
var commandScopedCommand = mech.run(Coroutine::park).named("Command-Scoped Default Command");
|
||||
var scopingCommand =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
co -> {
|
||||
mech.setDefaultCommand(commandScopedCommand);
|
||||
co.park();
|
||||
@@ -126,8 +124,7 @@ class SchedulerDefaultCommandTests extends CommandTestBase {
|
||||
var commandScopedCommand = mech.run(Coroutine::park).named("Command-Scoped Default Command");
|
||||
|
||||
final Command scopingCommand =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
co -> {
|
||||
mech.setDefaultCommand(commandScopedCommand);
|
||||
co.park();
|
||||
|
||||
@@ -43,17 +43,14 @@ class SchedulerErrorHandlingTests extends CommandTestBase {
|
||||
@Test
|
||||
void nestedErrorDetection() {
|
||||
var command =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
co -> {
|
||||
co.await(
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
c2 -> {
|
||||
new Trigger(m_scheduler, () -> true)
|
||||
.onTrue(
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
c3 -> {
|
||||
// Throws IndexOutOfBoundsException
|
||||
var unused = new ArrayList<>(0).get(-1);
|
||||
@@ -95,10 +92,9 @@ class SchedulerErrorHandlingTests extends CommandTestBase {
|
||||
|
||||
@Test
|
||||
void commandEncounteringErrorCancelsChildren() {
|
||||
var child = Command.noRequirements().executing(Coroutine::park).named("Child 1");
|
||||
var child = Command.noRequirements(Coroutine::park).named("Child 1");
|
||||
var command =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
co -> {
|
||||
co.fork(child);
|
||||
throw new RuntimeException("The exception");
|
||||
@@ -118,15 +114,13 @@ class SchedulerErrorHandlingTests extends CommandTestBase {
|
||||
@Test
|
||||
void childCommandEncounteringErrorCancelsParent() {
|
||||
var child =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
co -> {
|
||||
throw new RuntimeException("The exception"); // note: bubbles up to the parent
|
||||
})
|
||||
.named("Child 1");
|
||||
var command =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
co -> {
|
||||
co.await(child);
|
||||
co.park(); // pretend other things would happen after the child
|
||||
@@ -145,16 +139,14 @@ class SchedulerErrorHandlingTests extends CommandTestBase {
|
||||
@SuppressWarnings("PMD.CompareObjectsWithEquals")
|
||||
void childCommandEncounteringErrorAfterRemountCancelsParent() {
|
||||
var child =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
co -> {
|
||||
co.yield();
|
||||
throw new RuntimeException("The exception"); // does not bubble up to the parent
|
||||
})
|
||||
.named("Child 1");
|
||||
var command =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
co -> {
|
||||
co.await(child);
|
||||
co.park(); // pretend other things would happen after the child
|
||||
|
||||
@@ -41,7 +41,7 @@ class SchedulerSideloadFunctionTests extends CommandTestBase {
|
||||
|
||||
@Test
|
||||
void sideloadSchedulingCommand() {
|
||||
var command = Command.noRequirements().executing(Coroutine::park).named("Command");
|
||||
var command = Command.noRequirements(Coroutine::park).named("Command");
|
||||
// one-shot sideload forks a command and immediately exits
|
||||
m_scheduler.sideload(co -> co.fork(command));
|
||||
m_scheduler.run();
|
||||
@@ -51,10 +51,9 @@ class SchedulerSideloadFunctionTests extends CommandTestBase {
|
||||
|
||||
@Test
|
||||
void childCommandEscapesViaSideload() {
|
||||
var child = Command.noRequirements().executing(Coroutine::park).named("Child");
|
||||
var child = Command.noRequirements(Coroutine::park).named("Child");
|
||||
var parent =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
parentCoroutine -> {
|
||||
m_scheduler.sideload(sideloadCoroutine -> sideloadCoroutine.fork(child));
|
||||
})
|
||||
@@ -73,7 +72,7 @@ class SchedulerSideloadFunctionTests extends CommandTestBase {
|
||||
|
||||
@Test
|
||||
void sideloadCancelingCommand() {
|
||||
var command = Command.noRequirements().executing(Coroutine::park).named("Command");
|
||||
var command = Command.noRequirements(Coroutine::park).named("Command");
|
||||
m_scheduler.schedule(command);
|
||||
m_scheduler.run();
|
||||
assertTrue(m_scheduler.isRunning(command), "command should have started");
|
||||
@@ -89,7 +88,7 @@ class SchedulerSideloadFunctionTests extends CommandTestBase {
|
||||
void sideloadAffectsStateForTriggerInSameCycle() {
|
||||
AtomicBoolean signal = new AtomicBoolean(false);
|
||||
var trigger = new Trigger(m_scheduler, signal::get);
|
||||
var command = Command.noRequirements().executing(Coroutine::park).named("Command");
|
||||
var command = Command.noRequirements(Coroutine::park).named("Command");
|
||||
trigger.onTrue(command);
|
||||
m_scheduler.sideload(co -> signal.set(true));
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@ class SchedulerTelemetryTests extends CommandTestBase {
|
||||
m_scheduler.schedule(group);
|
||||
m_scheduler.run();
|
||||
|
||||
var scheduledCommand1 = Command.noRequirements().executing(Coroutine::park).named("Command 1");
|
||||
var scheduledCommand2 = Command.noRequirements().executing(Coroutine::park).named("Command 2");
|
||||
var scheduledCommand1 = Command.noRequirements(Coroutine::park).named("Command 1");
|
||||
var scheduledCommand2 = Command.noRequirements(Coroutine::park).named("Command 2");
|
||||
m_scheduler.schedule(scheduledCommand1);
|
||||
m_scheduler.schedule(scheduledCommand2);
|
||||
|
||||
|
||||
@@ -18,8 +18,7 @@ class SchedulerTest extends CommandTestBase {
|
||||
var enabled = new AtomicBoolean(false);
|
||||
var ran = new AtomicBoolean(false);
|
||||
var command =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
coroutine -> {
|
||||
do {
|
||||
coroutine.yield();
|
||||
@@ -58,8 +57,7 @@ class SchedulerTest extends CommandTestBase {
|
||||
|
||||
for (int cmdCount = 0; cmdCount < numCommands; cmdCount++) {
|
||||
var command =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
coroutine -> {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
mechanism.m_x++;
|
||||
@@ -114,8 +112,7 @@ class SchedulerTest extends CommandTestBase {
|
||||
|
||||
// the group has no requirements, but can schedule child commands that do
|
||||
var group =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
co -> {
|
||||
co.awaitAll(
|
||||
m1.run(Coroutine::park).named("M1 Command"),
|
||||
|
||||
@@ -25,8 +25,7 @@ class SchedulerTimingTests extends CommandTestBase {
|
||||
// equivalent to calling Coroutine.park(). No deleterious side effects other than stalling
|
||||
// the command
|
||||
AtomicReference<Command> commandRef = new AtomicReference<>();
|
||||
var command =
|
||||
Command.noRequirements().executing(co -> co.await(commandRef.get())).named("Self Await");
|
||||
var command = Command.noRequirements(co -> co.await(commandRef.get())).named("Self Await");
|
||||
commandRef.set(command);
|
||||
|
||||
m_scheduler.schedule(command);
|
||||
@@ -49,8 +48,8 @@ class SchedulerTimingTests extends CommandTestBase {
|
||||
//
|
||||
// Externally canceling child allows parent to continue
|
||||
// Externally canceling parent cancels both
|
||||
var parent = Command.noRequirements().executing(co -> co.await(childRef.get())).named("Parent");
|
||||
var child = Command.noRequirements().executing(co -> co.await(parentRef.get())).named("Child");
|
||||
var parent = Command.noRequirements(co -> co.await(childRef.get())).named("Parent");
|
||||
var child = Command.noRequirements(co -> co.await(parentRef.get())).named("Child");
|
||||
parentRef.set(parent);
|
||||
childRef.set(child);
|
||||
|
||||
@@ -87,8 +86,7 @@ class SchedulerTimingTests extends CommandTestBase {
|
||||
//
|
||||
// Externally canceling either command allows the other to exit
|
||||
var command1 =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
co -> {
|
||||
co.yield();
|
||||
co.await(ref2.get());
|
||||
@@ -96,8 +94,7 @@ class SchedulerTimingTests extends CommandTestBase {
|
||||
})
|
||||
.named("Command 1");
|
||||
var command2 =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
co -> {
|
||||
co.yield();
|
||||
co.await(ref1.get());
|
||||
@@ -134,8 +131,7 @@ class SchedulerTimingTests extends CommandTestBase {
|
||||
AtomicInteger runCount = new AtomicInteger(0);
|
||||
|
||||
var inner =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
co -> {
|
||||
runCount.incrementAndGet();
|
||||
co.yield();
|
||||
@@ -145,7 +141,7 @@ class SchedulerTimingTests extends CommandTestBase {
|
||||
})
|
||||
.named("Inner");
|
||||
|
||||
var outer = Command.noRequirements().executing(co -> co.await(inner)).named("Outer");
|
||||
var outer = Command.noRequirements(co -> co.await(inner)).named("Outer");
|
||||
m_scheduler.schedule(outer);
|
||||
m_scheduler.run();
|
||||
|
||||
@@ -159,8 +155,7 @@ class SchedulerTimingTests extends CommandTestBase {
|
||||
|
||||
AtomicBoolean completedWait = new AtomicBoolean(false);
|
||||
var command =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
co -> {
|
||||
co.wait(Milliseconds.of(1));
|
||||
completedWait.set(true);
|
||||
@@ -184,8 +179,7 @@ class SchedulerTimingTests extends CommandTestBase {
|
||||
RobotController.setTimeSource(time::get);
|
||||
AtomicBoolean completedWait = new AtomicBoolean(false);
|
||||
var command =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
co -> {
|
||||
co.wait(Milliseconds.of(1));
|
||||
completedWait.set(true);
|
||||
@@ -212,8 +206,7 @@ class SchedulerTimingTests extends CommandTestBase {
|
||||
void awaitingExitsImmediatelyWithoutAOneLoopDelay() {
|
||||
AtomicInteger innerRuns = new AtomicInteger(0);
|
||||
var inner =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
co -> {
|
||||
// executed immediately when forked
|
||||
innerRuns.incrementAndGet();
|
||||
@@ -224,7 +217,7 @@ class SchedulerTimingTests extends CommandTestBase {
|
||||
})
|
||||
.named("Inner");
|
||||
|
||||
var outer = Command.noRequirements().executing(co -> co.await(inner)).named("Outer");
|
||||
var outer = Command.noRequirements(co -> co.await(inner)).named("Outer");
|
||||
m_scheduler.schedule(outer);
|
||||
|
||||
// First run: runs outer, forks inner, inner runs to its first yield, outer yields
|
||||
|
||||
@@ -14,7 +14,7 @@ import org.junit.jupiter.api.Test;
|
||||
class SequentialGroupBuilderTest {
|
||||
@Test
|
||||
void andThenSingle() {
|
||||
var c1 = Command.noRequirements().executing(Coroutine::park).named("C1");
|
||||
var c1 = Command.noRequirements(Coroutine::park).named("C1");
|
||||
|
||||
var builder = new SequentialGroupBuilder();
|
||||
var sequence = builder.andThen(c1).named("Seq");
|
||||
@@ -25,8 +25,8 @@ class SequentialGroupBuilderTest {
|
||||
|
||||
@Test
|
||||
void andThenMultiple() {
|
||||
var c1 = Command.noRequirements().executing(Coroutine::park).named("C1");
|
||||
var c2 = Command.noRequirements().executing(Coroutine::park).named("C2");
|
||||
var c1 = Command.noRequirements(Coroutine::park).named("C1");
|
||||
var c2 = Command.noRequirements(Coroutine::park).named("C2");
|
||||
|
||||
var builder = new SequentialGroupBuilder();
|
||||
var sequence = builder.andThen(c1, c2).named("Seq");
|
||||
@@ -38,8 +38,8 @@ class SequentialGroupBuilderTest {
|
||||
|
||||
@Test
|
||||
void andThenRepeated() {
|
||||
var c1 = Command.noRequirements().executing(Coroutine::park).named("C1");
|
||||
var c2 = Command.noRequirements().executing(Coroutine::park).named("C2");
|
||||
var c1 = Command.noRequirements(Coroutine::park).named("C1");
|
||||
var c2 = Command.noRequirements(Coroutine::park).named("C2");
|
||||
|
||||
var builder = new SequentialGroupBuilder();
|
||||
var sequence = builder.andThen(c1).andThen(c2).named("Seq");
|
||||
@@ -69,7 +69,7 @@ class SequentialGroupBuilderTest {
|
||||
|
||||
@Test
|
||||
void untilReturnsParallelGroup() {
|
||||
var c1 = Command.noRequirements().executing(Coroutine::park).named("C1");
|
||||
var c1 = Command.noRequirements(Coroutine::park).named("C1");
|
||||
var builder = new SequentialGroupBuilder();
|
||||
var sequence = builder.andThen(c1).until(() -> false).named("Seq");
|
||||
assertInstanceOf(ParallelGroup.class, sequence);
|
||||
@@ -91,7 +91,7 @@ class SequentialGroupBuilderTest {
|
||||
|
||||
@Test
|
||||
void automaticNameWithOneCommand() {
|
||||
var c1 = Command.noRequirements().executing(Coroutine::park).named("C1");
|
||||
var c1 = Command.noRequirements(Coroutine::park).named("C1");
|
||||
var builder = new SequentialGroupBuilder();
|
||||
var sequence = builder.andThen(c1).withAutomaticName();
|
||||
assertEquals("C1", sequence.name());
|
||||
@@ -99,8 +99,8 @@ class SequentialGroupBuilderTest {
|
||||
|
||||
@Test
|
||||
void automaticNameWithMultipleCommands() {
|
||||
var c1 = Command.noRequirements().executing(Coroutine::park).named("C1");
|
||||
var c2 = Command.noRequirements().executing(Coroutine::park).named("C2");
|
||||
var c1 = Command.noRequirements(Coroutine::park).named("C1");
|
||||
var c2 = Command.noRequirements(Coroutine::park).named("C2");
|
||||
var builder = new SequentialGroupBuilder();
|
||||
var sequence = builder.andThen(c1, c2).withAutomaticName();
|
||||
assertEquals("C1 -> C2", sequence.name());
|
||||
|
||||
@@ -15,7 +15,7 @@ import org.junit.jupiter.api.Test;
|
||||
class SequentialGroupTest extends CommandTestBase {
|
||||
@Test
|
||||
void single() {
|
||||
var command = Command.noRequirements().executing(Coroutine::yield).named("The Command");
|
||||
var command = Command.noRequirements(Coroutine::yield).named("The Command");
|
||||
|
||||
var sequence = new SequentialGroup("The Sequence", List.of(command));
|
||||
m_scheduler.schedule(sequence);
|
||||
@@ -33,8 +33,8 @@ class SequentialGroupTest extends CommandTestBase {
|
||||
|
||||
@Test
|
||||
void twoCommands() {
|
||||
var c1 = Command.noRequirements().executing(Coroutine::yield).named("C1");
|
||||
var c2 = Command.noRequirements().executing(Coroutine::yield).named("C2");
|
||||
var c1 = Command.noRequirements(Coroutine::yield).named("C1");
|
||||
var c2 = Command.noRequirements(Coroutine::yield).named("C2");
|
||||
|
||||
var sequence = new SequentialGroup("C1 > C2", List.of(c1, c2));
|
||||
m_scheduler.schedule(sequence);
|
||||
|
||||
@@ -17,7 +17,7 @@ class TriggerTest extends CommandTestBase {
|
||||
void onTrue() {
|
||||
var signal = new AtomicBoolean(false);
|
||||
var trigger = new Trigger(m_scheduler, signal::get);
|
||||
var command = Command.noRequirements().executing(Coroutine::park).named("Command");
|
||||
var command = Command.noRequirements(Coroutine::park).named("Command");
|
||||
trigger.onTrue(command);
|
||||
|
||||
signal.set(true);
|
||||
@@ -34,7 +34,7 @@ class TriggerTest extends CommandTestBase {
|
||||
void onFalse() {
|
||||
var signal = new AtomicBoolean(false);
|
||||
var trigger = new Trigger(m_scheduler, signal::get);
|
||||
var command = Command.noRequirements().executing(Coroutine::park).named("Command");
|
||||
var command = Command.noRequirements(Coroutine::park).named("Command");
|
||||
trigger.onFalse(command);
|
||||
|
||||
m_scheduler.run();
|
||||
@@ -51,7 +51,7 @@ class TriggerTest extends CommandTestBase {
|
||||
void whileTrue() {
|
||||
var signal = new AtomicBoolean(false);
|
||||
var trigger = new Trigger(m_scheduler, signal::get);
|
||||
var command = Command.noRequirements().executing(Coroutine::park).named("Command");
|
||||
var command = Command.noRequirements(Coroutine::park).named("Command");
|
||||
trigger.whileTrue(command);
|
||||
|
||||
signal.set(true);
|
||||
@@ -68,7 +68,7 @@ class TriggerTest extends CommandTestBase {
|
||||
void whileFalse() {
|
||||
var signal = new AtomicBoolean(false);
|
||||
var trigger = new Trigger(m_scheduler, signal::get);
|
||||
var command = Command.noRequirements().executing(Coroutine::park).named("Command");
|
||||
var command = Command.noRequirements(Coroutine::park).named("Command");
|
||||
trigger.whileFalse(command);
|
||||
|
||||
m_scheduler.run();
|
||||
@@ -84,7 +84,7 @@ class TriggerTest extends CommandTestBase {
|
||||
void toggleOnTrue() {
|
||||
var signal = new AtomicBoolean(false);
|
||||
var trigger = new Trigger(m_scheduler, signal::get);
|
||||
var command = Command.noRequirements().executing(Coroutine::park).named("Command");
|
||||
var command = Command.noRequirements(Coroutine::park).named("Command");
|
||||
trigger.toggleOnTrue(command);
|
||||
|
||||
m_scheduler.run();
|
||||
@@ -107,7 +107,7 @@ class TriggerTest extends CommandTestBase {
|
||||
void toggleOnFalse() {
|
||||
var signal = new AtomicBoolean(false);
|
||||
var trigger = new Trigger(m_scheduler, signal::get);
|
||||
var command = Command.noRequirements().executing(Coroutine::park).named("Command");
|
||||
var command = Command.noRequirements(Coroutine::park).named("Command");
|
||||
trigger.toggleOnFalse(command);
|
||||
|
||||
m_scheduler.run();
|
||||
@@ -128,8 +128,7 @@ class TriggerTest extends CommandTestBase {
|
||||
var innerSignal = new AtomicBoolean(false);
|
||||
|
||||
var inner =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
co -> {
|
||||
while (true) {
|
||||
innerRan.set(true);
|
||||
@@ -139,8 +138,7 @@ class TriggerTest extends CommandTestBase {
|
||||
.named("Inner");
|
||||
|
||||
var outer =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
co -> {
|
||||
new Trigger(m_scheduler, innerSignal::get).onTrue(inner);
|
||||
// If we yield, then the outer command exits and immediately cancels the
|
||||
@@ -170,7 +168,7 @@ class TriggerTest extends CommandTestBase {
|
||||
var triggerSignal = new AtomicBoolean(false);
|
||||
var trigger = new Trigger(m_scheduler, triggerSignal::get);
|
||||
|
||||
var command = Command.noRequirements().executing(Coroutine::park).named("Command");
|
||||
var command = Command.noRequirements(Coroutine::park).named("Command");
|
||||
trigger.addBinding(scope, BindingType.RUN_WHILE_HIGH, command);
|
||||
|
||||
triggerSignal.set(true);
|
||||
@@ -209,7 +207,7 @@ class TriggerTest extends CommandTestBase {
|
||||
var triggerSignal = new AtomicBoolean(false);
|
||||
var trigger = new Trigger(m_scheduler, triggerSignal::get);
|
||||
|
||||
var command = Command.noRequirements().executing(Coroutine::park).named("Command");
|
||||
var command = Command.noRequirements(Coroutine::park).named("Command");
|
||||
trigger.whileTrue(command);
|
||||
|
||||
triggerSignal.set(true);
|
||||
@@ -230,8 +228,7 @@ class TriggerTest extends CommandTestBase {
|
||||
var triggeredCommandRan = new AtomicBoolean(false);
|
||||
|
||||
var inner =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
co -> {
|
||||
triggeredCommandRan.set(true);
|
||||
co.park();
|
||||
@@ -239,8 +236,7 @@ class TriggerTest extends CommandTestBase {
|
||||
.named("Inner");
|
||||
|
||||
var awaited =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
co -> {
|
||||
co.yield();
|
||||
condition.set(true);
|
||||
@@ -248,8 +244,7 @@ class TriggerTest extends CommandTestBase {
|
||||
.named("Awaited");
|
||||
|
||||
var outer =
|
||||
Command.noRequirements()
|
||||
.executing(
|
||||
Command.noRequirements(
|
||||
co -> {
|
||||
new Trigger(m_scheduler, condition::get).onTrue(inner);
|
||||
co.await(awaited);
|
||||
|
||||
@@ -144,7 +144,7 @@ void bindDriveButtons() {
|
||||
Trigger atScoringPosition = new Trigger(() -> getPosition().isNear(kScoringPosition));
|
||||
|
||||
Command autonomous() {
|
||||
return Command.noRequirements().executing(coroutine -> {
|
||||
return Command.noRequirements(coroutine -> {
|
||||
// This binding only exists while the autonomous command is running
|
||||
atScoringPosition.onTrue(score());
|
||||
|
||||
@@ -212,7 +212,7 @@ class ExampleOpmode extends PeriodicOpMode {
|
||||
robot.gamepad.leftBumper().onTrue(robot.mechanism.run(...).named("Bound Command"));
|
||||
|
||||
// A manually scheduled command in an opmode will be canceled when the opmode exits if it hasn't already exited on its own
|
||||
Scheduler.getInstance().schedule(Command.noRequirements().executing(coroutine -> {
|
||||
Scheduler.getInstance().schedule(Command.noRequirements(coroutine -> {
|
||||
// Change the default command while this command is running.
|
||||
// It will be reset to the opmode-scoped default command when this command exits.
|
||||
// If no opmode-scoped default command exists, it will be reset to the global default command.
|
||||
@@ -255,7 +255,7 @@ outside its command makes no sense, and an error will be thrown if attempting to
|
||||
|
||||
```java
|
||||
Coroutine coroutine;
|
||||
var badCommand = Command.noRequirements().executing(co -> {
|
||||
var badCommand = Command.noRequirements(co -> {
|
||||
coroutine = co;
|
||||
}).named("Do not do this");
|
||||
|
||||
@@ -357,13 +357,10 @@ compilation error.
|
||||
// OK - requirements, body, and name are all provided
|
||||
// Each builder method returns a different builder object that provides methods
|
||||
// for progressing to the next stage.
|
||||
Command command = Command.noRequirements().executing(...).named("Name");
|
||||
Command command = Command.noRequirements(...).named("Name");
|
||||
|
||||
// Compilation error! Missing the command body
|
||||
Command command = Command.noRequirements().named("Name");
|
||||
|
||||
// Compilation error! Missing the command name
|
||||
Command command = Command.noRequirements().executing(...);
|
||||
Command command = Command.noRequirements(...);
|
||||
```
|
||||
|
||||
#### Forced Naming
|
||||
|
||||
Reference in New Issue
Block a user