diff --git a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java
index bff828ac28..0fecef2338 100644
--- a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java
+++ b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java
@@ -286,14 +286,14 @@ public interface Command {
}
/**
- * Decorates this command to run "by proxy" by wrapping it in a {@link ProxyScheduleCommand}. This
- * is useful for "forking off" from command groups when the user does not wish to extend the
+ * Decorates this command to run "by proxy" by wrapping it in a {@link ProxyCommand}. This is
+ * useful for "forking off" from command groups when the user does not wish to extend the
* command's requirements to the entire command group.
*
* @return the decorated command
*/
- default ProxyScheduleCommand asProxy() {
- return new ProxyScheduleCommand(this);
+ default ProxyCommand asProxy() {
+ return new ProxyCommand(this);
}
/**
diff --git a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/ProxyCommand.java b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/ProxyCommand.java
new file mode 100644
index 0000000000..871d82922e
--- /dev/null
+++ b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/ProxyCommand.java
@@ -0,0 +1,76 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+package edu.wpi.first.wpilibj2.command;
+
+import static edu.wpi.first.wpilibj.util.ErrorMessages.requireNonNullParam;
+
+import java.util.function.Supplier;
+
+/**
+ * Schedules the given command when this command is initialized, and ends when it ends. Useful for
+ * forking off from CommandGroups. If this command is interrupted, it will cancel the command.
+ *
+ *
This class is provided by the NewCommands VendorDep
+ */
+public class ProxyCommand extends CommandBase {
+ private final Supplier m_supplier;
+ private Command m_command;
+
+ /**
+ * Creates a new ProxyCommand that schedules the supplied command when initialized, and ends when
+ * it is no longer scheduled. Useful for lazily creating commands at runtime.
+ *
+ * @param supplier the command supplier
+ */
+ public ProxyCommand(Supplier supplier) {
+ m_supplier = requireNonNullParam(supplier, "supplier", "ProxyCommand");
+ }
+
+ /**
+ * Creates a new ProxyCommand that schedules the given command when initialized, and ends when it
+ * is no longer scheduled.
+ *
+ * @param command the command to run by proxy
+ */
+ public ProxyCommand(Command command) {
+ this(() -> command);
+ }
+
+ @Override
+ public void initialize() {
+ m_command = m_supplier.get();
+ m_command.schedule();
+ }
+
+ @Override
+ public void end(boolean interrupted) {
+ if (interrupted) {
+ m_command.cancel();
+ }
+ m_command = null;
+ }
+
+ @Override
+ public void execute() {}
+
+ @Override
+ public boolean isFinished() {
+ // because we're between `initialize` and `end`, `m_command` is necessarily not null
+ // but if called otherwise and m_command is null,
+ // it's UB, so we can do whatever we want -- like return true.
+ return m_command == null || !m_command.isScheduled();
+ }
+
+ /**
+ * Whether the given command should run when the robot is disabled. Override to return true if the
+ * command should run when disabled.
+ *
+ * @return true. Otherwise, this proxy would cancel commands that do run when disabled.
+ */
+ @Override
+ public boolean runsWhenDisabled() {
+ return true;
+ }
+}
diff --git a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/ProxyScheduleCommand.java b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/ProxyScheduleCommand.java
index 858d9d0629..9ef82923a0 100644
--- a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/ProxyScheduleCommand.java
+++ b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/ProxyScheduleCommand.java
@@ -22,7 +22,10 @@ public class ProxyScheduleCommand extends CommandBase {
* when they are all no longer scheduled.
*
* @param toSchedule the commands to schedule
+ * @deprecated Replace with {@link ProxyCommand}, composing multiple of them in a {@link
+ * ParallelRaceGroup} if needed.
*/
+ @Deprecated
public ProxyScheduleCommand(Command... toSchedule) {
m_toSchedule = Set.of(toSchedule);
}
diff --git a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/SelectCommand.java b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/SelectCommand.java
index 3cf9f261fb..b3cd97b56d 100644
--- a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/SelectCommand.java
+++ b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/SelectCommand.java
@@ -63,7 +63,9 @@ public class SelectCommand extends CommandBase {
* Creates a new selectcommand.
*
* @param toRun a supplier providing the command to run
+ * @deprecated Replace with {@link ProxyCommand}
*/
+ @Deprecated
public SelectCommand(Supplier toRun) {
m_commands = null;
m_selector = null;
diff --git a/wpilibNewCommands/src/main/native/cpp/frc2/command/Command.cpp b/wpilibNewCommands/src/main/native/cpp/frc2/command/Command.cpp
index ee86b72ef3..45c7febf88 100644
--- a/wpilibNewCommands/src/main/native/cpp/frc2/command/Command.cpp
+++ b/wpilibNewCommands/src/main/native/cpp/frc2/command/Command.cpp
@@ -12,7 +12,6 @@
#include "frc2/command/ParallelDeadlineGroup.h"
#include "frc2/command/ParallelRaceGroup.h"
#include "frc2/command/PerpetualCommand.h"
-#include "frc2/command/ProxyScheduleCommand.h"
#include "frc2/command/RepeatCommand.h"
#include "frc2/command/SequentialCommandGroup.h"
#include "frc2/command/WaitCommand.h"
diff --git a/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandPtr.cpp b/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandPtr.cpp
index a51be45ccb..0399e866b2 100644
--- a/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandPtr.cpp
+++ b/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandPtr.cpp
@@ -13,7 +13,7 @@
#include "frc2/command/ParallelDeadlineGroup.h"
#include "frc2/command/ParallelRaceGroup.h"
#include "frc2/command/PrintCommand.h"
-#include "frc2/command/ProxyScheduleCommand.h"
+#include "frc2/command/ProxyCommand.h"
#include "frc2/command/RepeatCommand.h"
#include "frc2/command/SequentialCommandGroup.h"
#include "frc2/command/WaitCommand.h"
@@ -37,7 +37,7 @@ CommandPtr CommandPtr::Repeatedly() && {
CommandPtr CommandPtr::AsProxy() && {
AssertValid();
- m_ptr = std::make_unique(std::move(m_ptr));
+ m_ptr = std::make_unique(std::move(m_ptr));
return std::move(*this);
}
diff --git a/wpilibNewCommands/src/main/native/cpp/frc2/command/Commands.cpp b/wpilibNewCommands/src/main/native/cpp/frc2/command/Commands.cpp
index 2ecd9b2ddc..1932e45f67 100644
--- a/wpilibNewCommands/src/main/native/cpp/frc2/command/Commands.cpp
+++ b/wpilibNewCommands/src/main/native/cpp/frc2/command/Commands.cpp
@@ -10,9 +10,7 @@
#include "frc2/command/ParallelCommandGroup.h"
#include "frc2/command/ParallelDeadlineGroup.h"
#include "frc2/command/ParallelRaceGroup.h"
-#include "frc2/command/PerpetualCommand.h"
#include "frc2/command/PrintCommand.h"
-#include "frc2/command/ProxyScheduleCommand.h"
#include "frc2/command/RunCommand.h"
#include "frc2/command/SequentialCommandGroup.h"
#include "frc2/command/WaitCommand.h"
diff --git a/wpilibNewCommands/src/main/native/cpp/frc2/command/ProxyCommand.cpp b/wpilibNewCommands/src/main/native/cpp/frc2/command/ProxyCommand.cpp
new file mode 100644
index 0000000000..0fc7cdf602
--- /dev/null
+++ b/wpilibNewCommands/src/main/native/cpp/frc2/command/ProxyCommand.cpp
@@ -0,0 +1,37 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#include "frc2/command/ProxyCommand.h"
+
+using namespace frc2;
+
+ProxyCommand::ProxyCommand(wpi::unique_function supplier)
+ : m_supplier(std::move(supplier)) {}
+
+ProxyCommand::ProxyCommand(Command* command)
+ : m_supplier([command] { return command; }) {}
+
+ProxyCommand::ProxyCommand(std::unique_ptr command)
+ : m_supplier([command = std::move(command)] { return command.get(); }) {}
+
+void ProxyCommand::Initialize() {
+ m_command = m_supplier();
+ m_command->Schedule();
+}
+
+void ProxyCommand::End(bool interrupted) {
+ if (interrupted) {
+ m_command->Cancel();
+ }
+ m_command = nullptr;
+}
+
+void ProxyCommand::Execute() {}
+
+bool ProxyCommand::IsFinished() {
+ // because we're between `initialize` and `end`, `m_command` is necessarily
+ // not null but if called otherwise and m_command is null, it's UB, so we can
+ // do whatever we want -- like return true.
+ return m_command == nullptr || !m_command->IsScheduled();
+}
diff --git a/wpilibNewCommands/src/main/native/cpp/frc2/command/ProxyScheduleCommand.cpp b/wpilibNewCommands/src/main/native/cpp/frc2/command/ProxyScheduleCommand.cpp
index a2cc827f39..dd0e2a7b3d 100644
--- a/wpilibNewCommands/src/main/native/cpp/frc2/command/ProxyScheduleCommand.cpp
+++ b/wpilibNewCommands/src/main/native/cpp/frc2/command/ProxyScheduleCommand.cpp
@@ -15,13 +15,6 @@ ProxyScheduleCommand::ProxyScheduleCommand(Command* toSchedule) {
SetInsert(m_toSchedule, {&toSchedule, 1});
}
-ProxyScheduleCommand::ProxyScheduleCommand(
- std::unique_ptr&& toSchedule)
- : m_owning(std::move(toSchedule)) {
- Command* ptr = m_owning.get();
- SetInsert(m_toSchedule, {&ptr, 1});
-}
-
void ProxyScheduleCommand::Initialize() {
for (auto* command : m_toSchedule) {
command->Schedule();
diff --git a/wpilibNewCommands/src/main/native/include/frc2/command/Command.h b/wpilibNewCommands/src/main/native/include/frc2/command/Command.h
index c870a47095..5ba47363b9 100644
--- a/wpilibNewCommands/src/main/native/include/frc2/command/Command.h
+++ b/wpilibNewCommands/src/main/native/include/frc2/command/Command.h
@@ -25,7 +25,6 @@ std::string GetTypeName(const T& type) {
}
class PerpetualCommand;
-class ProxyScheduleCommand;
/**
* A state machine representing a complete action to be performed by the robot.
@@ -225,7 +224,7 @@ safe) semantics.
/**
* Decorates this command to run "by proxy" by wrapping it in a
- * ProxyScheduleCommand. This is useful for "forking off" from command groups
+ * ProxyCommand. This is useful for "forking off" from command groups
* when the user does not wish to extend the command's requirements to the
* entire command group.
*
diff --git a/wpilibNewCommands/src/main/native/include/frc2/command/CommandPtr.h b/wpilibNewCommands/src/main/native/include/frc2/command/CommandPtr.h
index b4fa60dcfe..2390e9dca2 100644
--- a/wpilibNewCommands/src/main/native/include/frc2/command/CommandPtr.h
+++ b/wpilibNewCommands/src/main/native/include/frc2/command/CommandPtr.h
@@ -49,7 +49,7 @@ class CommandPtr final {
/**
* Decorates this command to run "by proxy" by wrapping it in a
- * ProxyScheduleCommand. This is useful for "forking off" from command groups
+ * ProxyCommand. This is useful for "forking off" from command groups
* when the user does not wish to extend the command's requirements to the
* entire command group.
*
diff --git a/wpilibNewCommands/src/main/native/include/frc2/command/ProxyCommand.h b/wpilibNewCommands/src/main/native/include/frc2/command/ProxyCommand.h
new file mode 100644
index 0000000000..f553f18776
--- /dev/null
+++ b/wpilibNewCommands/src/main/native/include/frc2/command/ProxyCommand.h
@@ -0,0 +1,68 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#pragma once
+
+#include
+#include
+
+#include
+
+#include "frc2/command/CommandBase.h"
+#include "frc2/command/CommandHelper.h"
+#include "frc2/command/SetUtilities.h"
+
+namespace frc2 {
+/**
+ * Schedules the given command when this command is initialized, and ends when
+ * it ends. Useful for forking off from CommandGroups. If this command is
+ * interrupted, it will cancel the command.
+ *
+ * This class is provided by the NewCommands VendorDep
+ */
+class ProxyCommand : public CommandHelper {
+ public:
+ /**
+ * Creates a new ProxyCommand that schedules the supplied command when
+ * initialized, and ends when it is no longer scheduled. Useful for lazily
+ * creating commands at runtime.
+ *
+ * @param supplier the command supplier
+ */
+ explicit ProxyCommand(wpi::unique_function supplier);
+
+ /**
+ * Creates a new ProxyCommand that schedules the given command when
+ * initialized, and ends when it is no longer scheduled.
+ *
+ * @param command the command to run by proxy
+ */
+ explicit ProxyCommand(Command* command);
+
+ /**
+ * Creates a new ProxyCommand that schedules the given command when
+ * initialized, and ends when it is no longer scheduled.
+ *
+ * Note that this constructor passes ownership of the given command to the
+ * returned ProxyCommand.
+ *
+ * @param command the command to schedule
+ */
+ explicit ProxyCommand(std::unique_ptr command);
+
+ ProxyCommand(ProxyCommand&& other) = default;
+
+ void Initialize() override;
+
+ void End(bool interrupted) override;
+
+ void Execute() override;
+
+ bool IsFinished() override;
+
+ private:
+ wpi::unique_function m_supplier;
+ Command* m_command = nullptr;
+};
+} // namespace frc2
diff --git a/wpilibNewCommands/src/main/native/include/frc2/command/ProxyScheduleCommand.h b/wpilibNewCommands/src/main/native/include/frc2/command/ProxyScheduleCommand.h
index e20d329389..f79b5492c7 100644
--- a/wpilibNewCommands/src/main/native/include/frc2/command/ProxyScheduleCommand.h
+++ b/wpilibNewCommands/src/main/native/include/frc2/command/ProxyScheduleCommand.h
@@ -8,6 +8,7 @@
#include
#include
+#include
#include "frc2/command/CommandBase.h"
#include "frc2/command/CommandHelper.h"
@@ -30,22 +31,14 @@ class ProxyScheduleCommand
* initialized, and ends when they are all no longer scheduled.
*
* @param toSchedule the commands to schedule
+ * @deprecated Replace with {@link ProxyCommand},
+ * composing multiple of them in a {@link ParallelRaceGroup} if needed.
*/
+ WPI_DEPRECATED("Replace with ProxyCommand")
explicit ProxyScheduleCommand(std::span toSchedule);
explicit ProxyScheduleCommand(Command* toSchedule);
- /**
- * Creates a new ProxyScheduleCommand that schedules the given command when
- * initialized, and ends when it is no longer scheduled.
- *
- * Note that this constructor passes ownership of the given command to the
- * returned ProxyScheduleCommand.
- *
- * @param toSchedule the command to schedule
- */
- explicit ProxyScheduleCommand(std::unique_ptr&& toSchedule);
-
ProxyScheduleCommand(ProxyScheduleCommand&& other) = default;
void Initialize() override;
diff --git a/wpilibNewCommands/src/main/native/include/frc2/command/SelectCommand.h b/wpilibNewCommands/src/main/native/include/frc2/command/SelectCommand.h
index 202474ef7c..d2b9ec39e7 100644
--- a/wpilibNewCommands/src/main/native/include/frc2/command/SelectCommand.h
+++ b/wpilibNewCommands/src/main/native/include/frc2/command/SelectCommand.h
@@ -108,7 +108,10 @@ class SelectCommand : public CommandHelper> {
* Creates a new selectcommand.
*
* @param toRun a supplier providing the command to run
+ * @deprecated Replace with {@link ProxyCommand},
+ * composing multiple of them in a {@link ParallelRaceGroup} if needed.
*/
+ WPI_DEPRECATED("Replace with ProxyCommand")
explicit SelectCommand(std::function toRun)
: m_toRun{std::move(toRun)} {}
diff --git a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/ProxyScheduleCommandTest.java b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/ProxyCommandTest.java
similarity index 80%
rename from wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/ProxyScheduleCommandTest.java
rename to wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/ProxyCommandTest.java
index eaf3216602..c4b43a609b 100644
--- a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/ProxyScheduleCommandTest.java
+++ b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/ProxyCommandTest.java
@@ -11,14 +11,14 @@ import static org.mockito.Mockito.verify;
import java.util.concurrent.atomic.AtomicBoolean;
import org.junit.jupiter.api.Test;
-class ProxyScheduleCommandTest extends CommandTestBase {
+class ProxyCommandTest extends CommandTestBase {
@Test
- void proxyScheduleCommandScheduleTest() {
+ void proxyCommandScheduleTest() {
try (CommandScheduler scheduler = new CommandScheduler()) {
MockCommandHolder command1Holder = new MockCommandHolder(true);
Command command1 = command1Holder.getMock();
- ProxyScheduleCommand scheduleCommand = new ProxyScheduleCommand(command1);
+ ProxyCommand scheduleCommand = new ProxyCommand(command1);
scheduler.schedule(scheduleCommand);
@@ -27,13 +27,13 @@ class ProxyScheduleCommandTest extends CommandTestBase {
}
@Test
- void proxyScheduleCommandEndTest() {
+ void proxyCommandEndTest() {
try (CommandScheduler scheduler = CommandScheduler.getInstance()) {
AtomicBoolean cond = new AtomicBoolean();
WaitUntilCommand command = new WaitUntilCommand(cond::get);
- ProxyScheduleCommand scheduleCommand = new ProxyScheduleCommand(command);
+ ProxyCommand scheduleCommand = new ProxyCommand(command);
scheduler.schedule(scheduleCommand);
diff --git a/wpilibNewCommands/src/test/native/cpp/frc2/command/ProxyScheduleCommandTest.cpp b/wpilibNewCommands/src/test/native/cpp/frc2/command/ProxyCommandTest.cpp
similarity index 79%
rename from wpilibNewCommands/src/test/native/cpp/frc2/command/ProxyScheduleCommandTest.cpp
rename to wpilibNewCommands/src/test/native/cpp/frc2/command/ProxyCommandTest.cpp
index 9c66769990..81ec9d1432 100644
--- a/wpilibNewCommands/src/test/native/cpp/frc2/command/ProxyScheduleCommandTest.cpp
+++ b/wpilibNewCommands/src/test/native/cpp/frc2/command/ProxyCommandTest.cpp
@@ -7,20 +7,20 @@
#include "CommandTestBase.h"
#include "frc2/command/CommandPtr.h"
#include "frc2/command/InstantCommand.h"
-#include "frc2/command/ProxyScheduleCommand.h"
+#include "frc2/command/ProxyCommand.h"
#include "frc2/command/WaitUntilCommand.h"
using namespace frc2;
-class ProxyScheduleCommandTest : public CommandTestBase {};
+class ProxyCommandTest : public CommandTestBase {};
-TEST_F(ProxyScheduleCommandTest, NonOwningCommandSchedule) {
+TEST_F(ProxyCommandTest, NonOwningCommandSchedule) {
CommandScheduler& scheduler = CommandScheduler::GetInstance();
bool scheduled = false;
InstantCommand toSchedule([&scheduled] { scheduled = true; }, {});
- ProxyScheduleCommand command(&toSchedule);
+ ProxyCommand command(&toSchedule);
scheduler.Schedule(&command);
scheduler.Run();
@@ -28,14 +28,14 @@ TEST_F(ProxyScheduleCommandTest, NonOwningCommandSchedule) {
EXPECT_TRUE(scheduled);
}
-TEST_F(ProxyScheduleCommandTest, NonOwningCommandEnd) {
+TEST_F(ProxyCommandTest, NonOwningCommandEnd) {
CommandScheduler& scheduler = CommandScheduler::GetInstance();
bool finished = false;
WaitUntilCommand toSchedule([&finished] { return finished; });
- ProxyScheduleCommand command(&toSchedule);
+ ProxyCommand command(&toSchedule);
scheduler.Schedule(&command);
scheduler.Run();
@@ -47,7 +47,7 @@ TEST_F(ProxyScheduleCommandTest, NonOwningCommandEnd) {
EXPECT_FALSE(scheduler.IsScheduled(&command));
}
-TEST_F(ProxyScheduleCommandTest, OwningCommandSchedule) {
+TEST_F(ProxyCommandTest, OwningCommandSchedule) {
CommandScheduler& scheduler = CommandScheduler::GetInstance();
bool scheduled = false;
@@ -61,7 +61,7 @@ TEST_F(ProxyScheduleCommandTest, OwningCommandSchedule) {
EXPECT_TRUE(scheduled);
}
-TEST_F(ProxyScheduleCommandTest, OwningCommandEnd) {
+TEST_F(ProxyCommandTest, OwningCommandEnd) {
CommandScheduler& scheduler = CommandScheduler::GetInstance();
bool finished = false;