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 73d562fc5f..bff828ac28 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 @@ -430,14 +430,32 @@ public interface Command { } /** - * Gets the name of this Command. + * Gets the name of this Command. Defaults to the simple class name if not overridden. * - * @return Name + * @return The display name of the Command */ default String getName() { return this.getClass().getSimpleName(); } + /** + * Sets the name of this Command. Nullop if not overridden. + * + * @param name The display name of the Command. + */ + default void setName(String name) {} + + /** + * Decorates this Command with a name. Is an inline function for #setName(String); + * + * @param name name + * @return the decorated Command + */ + default Command withName(String name) { + this.setName(name); + return this; + } + /** * An enum describing the command's behavior when another command with a shared requirement is * scheduled. diff --git a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/CommandBase.java b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/CommandBase.java index 5b577bd3cc..a8e591c5c7 100644 --- a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/CommandBase.java +++ b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/CommandBase.java @@ -51,21 +51,11 @@ public abstract class CommandBase implements Sendable, Command { * * @param name name */ + @Override public void setName(String name) { SendableRegistry.setName(this, name); } - /** - * Decorates this Command with a name. Is an inline function for #setName(String); - * - * @param name name - * @return the decorated Command - */ - public CommandBase withName(String name) { - this.setName(name); - return this; - } - /** * Gets the subsystem name of this Command. * diff --git a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Commands.java b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Commands.java new file mode 100644 index 0000000000..862e3c11ae --- /dev/null +++ b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Commands.java @@ -0,0 +1,210 @@ +// 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.Map; +import java.util.function.BooleanSupplier; +import java.util.function.Supplier; + +/** + * Namespace for command factory methods. + * + *

For convenience, you might want to static import the members of this class. + */ +public final class Commands { + /** + * Constructs a command that does nothing, finishing immediately. + * + * @return the command + */ + public static Command none() { + return new InstantCommand(); + } + + // Action Commands + + /** + * Constructs a command that runs an action once and finishes. + * + * @param action the action to run + * @param requirements subsystems the action requires + * @return the command + * @see InstantCommand + */ + public static Command runOnce(Runnable action, Subsystem... requirements) { + return new InstantCommand(action, requirements); + } + + /** + * Constructs a command that runs an action every iteration until interrupted. + * + * @param action the action to run + * @param requirements subsystems the action requires + * @return the command + * @see RunCommand + */ + public static Command run(Runnable action, Subsystem... requirements) { + return new RunCommand(action, requirements); + } + + /** + * Constructs a command that runs an action once and another action when the command is + * interrupted. + * + * @param start the action to run on start + * @param end the action to run on interrupt + * @param requirements subsystems the action requires + * @return the command + * @see StartEndCommand + */ + public static Command startEnd(Runnable start, Runnable end, Subsystem... requirements) { + return new StartEndCommand(start, end, requirements); + } + + /** + * Constructs a command that runs an action every iteration until interrupted, and then runs a + * second action. + * + * @param run the action to run every iteration + * @param end the action to run on interrupt + * @param requirements subsystems the action requires + * @return the command + */ + public static Command runEnd(Runnable run, Runnable end, Subsystem... requirements) { + requireNonNullParam(end, "end", "Command.runEnd"); + return new FunctionalCommand( + () -> {}, run, interrupted -> end.run(), () -> false, requirements); + } + + /** + * Constructs a command that prints a message and finishes. + * + * @param message the message to print + * @return the command + * @see PrintCommand + */ + public static Command print(String message) { + return new PrintCommand(message); + } + + // Idling Commands + + /** + * Constructs a command that does nothing, finishing after a specified duration. + * + * @param seconds after how long the command finishes + * @return the command + * @see WaitCommand + */ + public static Command wait(double seconds) { + return new WaitCommand(seconds); + } + + /** + * Constructs a command that does nothing, finishing once a command becomes true. + * + * @param condition the condition + * @return the command + * @see WaitUntilCommand + */ + public static Command waitUntil(BooleanSupplier condition) { + return new WaitUntilCommand(condition); + } + + // Selector Commands + + /** + * Runs one of two commands, based on the boolean selector function. + * + * @param onTrue the command to run if the selector function returns true + * @param onFalse the command to run if the selector function returns false + * @param selector the selector function + * @return the command + * @see ConditionalCommand + */ + public static Command either(Command onTrue, Command onFalse, BooleanSupplier selector) { + return new ConditionalCommand(onTrue, onFalse, selector); + } + + /** + * Runs one of several commands, based on the selector function. + * + * @param selector the selector function + * @param commands map of commands to select from + * @return the command + * @see SelectCommand + */ + public static Command select(Map commands, Supplier selector) { + return new SelectCommand(commands, selector); + } + + /** + * Runs a group of commands in series, one after the other. + * + * @param commands the commands to include + * @return the command group + * @see SequentialCommandGroup + */ + public static Command sequence(Command... commands) { + return new SequentialCommandGroup(commands); + } + + // Command Groups + + /** + * Runs a group of commands in series, one after the other. Once the last command ends, the group + * is restarted. + * + * @param commands the commands to include + * @return the command group + * @see SequentialCommandGroup + * @see Command#repeatedly() + */ + public static Command repeatingSequence(Command... commands) { + return sequence(commands).repeatedly(); + } + + /** + * Runs a group of commands at the same time. Ends once all commands in the group finish. + * + * @param commands the commands to include + * @return the command + * @see ParallelCommandGroup + */ + public static Command parallel(Command... commands) { + return new ParallelCommandGroup(commands); + } + + /** + * Runs a group of commands at the same time. Ends once any command in the group finishes, and + * cancels the others. + * + * @param commands the commands to include + * @return the command group + * @see ParallelRaceGroup + */ + public static Command race(Command... commands) { + return new ParallelRaceGroup(commands); + } + + /** + * Runs a group of commands at the same time. Ends once a specific command finishes, and cancels + * the others. + * + * @param deadline the deadline command + * @param commands the commands to include + * @return the command group + * @see ParallelDeadlineGroup + */ + public static Command deadline(Command deadline, Command... commands) { + return new ParallelDeadlineGroup(deadline, commands); + } + + private Commands() { + throw new UnsupportedOperationException("This is a utility class"); + } +} diff --git a/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandPtr.cpp b/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandPtr.cpp index 22665381d9..565e5adc57 100644 --- a/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandPtr.cpp +++ b/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandPtr.cpp @@ -10,7 +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/RepeatCommand.h" #include "frc2/command/SequentialCommandGroup.h" diff --git a/wpilibNewCommands/src/main/native/cpp/frc2/command/Commands.cpp b/wpilibNewCommands/src/main/native/cpp/frc2/command/Commands.cpp new file mode 100644 index 0000000000..564c6c3702 --- /dev/null +++ b/wpilibNewCommands/src/main/native/cpp/frc2/command/Commands.cpp @@ -0,0 +1,135 @@ +// 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/Commands.h" + +#include "frc2/command/ConditionalCommand.h" +#include "frc2/command/FunctionalCommand.h" +#include "frc2/command/InstantCommand.h" +#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/SelectCommand.h" +#include "frc2/command/SequentialCommandGroup.h" +#include "frc2/command/WaitCommand.h" +#include "frc2/command/WaitUntilCommand.h" + +using namespace frc2; + +// Factories + +CommandPtr cmd::None() { + return InstantCommand().ToPtr(); +} + +CommandPtr cmd::RunOnce(std::function action, + std::initializer_list requirements) { + return InstantCommand(std::move(action), requirements).ToPtr(); +} + +CommandPtr cmd::RunOnce(std::function action, + std::span requirements) { + return InstantCommand(std::move(action), requirements).ToPtr(); +} + +CommandPtr cmd::Run(std::function action, + std::initializer_list requirements) { + return RunCommand(std::move(action), requirements).ToPtr(); +} + +CommandPtr cmd::Run(std::function action, + std::span requirements) { + return RunCommand(std::move(action), requirements).ToPtr(); +} + +CommandPtr cmd::StartEnd(std::function start, std::function end, + std::initializer_list requirements) { + return FunctionalCommand( + std::move(start), [] {}, + [end = std::move(end)](bool interrupted) { end(); }, + [] { return false; }, requirements) + .ToPtr(); +} + +CommandPtr cmd::StartEnd(std::function start, std::function end, + std::span requirements) { + return FunctionalCommand( + std::move(start), [] {}, + [end = std::move(end)](bool interrupted) { end(); }, + [] { return false; }, requirements) + .ToPtr(); +} + +CommandPtr cmd::RunEnd(std::function run, std::function end, + std::initializer_list requirements) { + return FunctionalCommand([] {}, std::move(run), + [end = std::move(end)](bool interrupted) { end(); }, + [] { return false; }, requirements) + .ToPtr(); +} + +CommandPtr cmd::RunEnd(std::function run, std::function end, + std::span requirements) { + return FunctionalCommand([] {}, std::move(run), + [end = std::move(end)](bool interrupted) { end(); }, + [] { return false; }, requirements) + .ToPtr(); +} + +CommandPtr cmd::Print(std::string_view msg) { + return PrintCommand(msg).ToPtr(); +} + +CommandPtr cmd::Wait(units::second_t duration) { + return WaitCommand(duration).ToPtr(); +} + +CommandPtr cmd::WaitUntil(std::function condition) { + return WaitUntilCommand(condition).ToPtr(); +} + +CommandPtr cmd::Either(CommandPtr&& onTrue, CommandPtr&& onFalse, + std::function selector) { + return ConditionalCommand(std::move(onTrue).Unwrap(), + std::move(onFalse).Unwrap(), std::move(selector)) + .ToPtr(); +} + +template +CommandPtr cmd::Select(std::function selector, + std::vector> commands) { + return SelectCommand(std::move(selector), + CommandPtr::UnwrapVector(std::move(commands))) + .ToPtr(); +} + +CommandPtr cmd::Sequence(std::vector&& commands) { + return SequentialCommandGroup(CommandPtr::UnwrapVector(std::move(commands))) + .ToPtr(); +} + +CommandPtr cmd::RepeatingSequence(std::vector&& commands) { + return Sequence(std::move(commands)).Repeatedly(); +} + +CommandPtr cmd::Parallel(std::vector&& commands) { + return ParallelCommandGroup(CommandPtr::UnwrapVector(std::move(commands))) + .ToPtr(); +} + +CommandPtr cmd::Race(std::vector&& commands) { + return ParallelRaceGroup(CommandPtr::UnwrapVector(std::move(commands))) + .ToPtr(); +} + +CommandPtr cmd::Deadline(CommandPtr&& deadline, + std::vector&& others) { + return ParallelDeadlineGroup(std::move(deadline).Unwrap(), + CommandPtr::UnwrapVector(std::move(others))) + .ToPtr(); +} diff --git a/wpilibNewCommands/src/main/native/include/frc2/command/Commands.h b/wpilibNewCommands/src/main/native/include/frc2/command/Commands.h new file mode 100644 index 0000000000..c1703825ad --- /dev/null +++ b/wpilibNewCommands/src/main/native/include/frc2/command/Commands.h @@ -0,0 +1,196 @@ +// 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 +#include +#include + +#include "frc2/command/CommandPtr.h" + +namespace frc2 { +class Subsystem; + +/** + * Namespace for command factories. + */ +namespace cmd { + +/** + * Constructs a command that does nothing, finishing immediately. + */ +[[nodiscard]] CommandPtr None(); + +// Action Commands + +/** + * Constructs a command that runs an action once and finishes. + * + * @param action the action to run + * @param requirements subsystems the action requires + */ +[[nodiscard]] CommandPtr RunOnce( + std::function action, + std::initializer_list requirements); + +/** + * Constructs a command that runs an action once and finishes. + * + * @param action the action to run + * @param requirements subsystems the action requires + */ +[[nodiscard]] CommandPtr RunOnce(std::function action, + std::span requirements = {}); + +/** + * Constructs a command that runs an action every iteration until interrupted. + * + * @param action the action to run + * @param requirements subsystems the action requires + */ +[[nodiscard]] CommandPtr Run(std::function action, + std::initializer_list requirements); + +/** + * Constructs a command that runs an action every iteration until interrupted. + * + * @param action the action to run + * @param requirements subsystems the action requires + */ +[[nodiscard]] CommandPtr Run(std::function action, + std::span requirements = {}); + +/** + * Constructs a command that runs an action once and another action when the + * command is interrupted. + * + * @param start the action to run on start + * @param end the action to run on interrupt + * @param requirements subsystems the action requires + */ +[[nodiscard]] CommandPtr StartEnd( + std::function start, std::function end, + std::initializer_list requirements); + +/** + * Constructs a command that runs an action once and another action when the + * command is interrupted. + * + * @param start the action to run on start + * @param end the action to run on interrupt + * @param requirements subsystems the action requires + */ +[[nodiscard]] CommandPtr StartEnd( + std::function start, std::function end, + std::span requirements = {}); + +/** + * Constructs a command that runs an action every iteration until interrupted, + * and then runs a second action. + * + * @param run the action to run every iteration + * @param end the action to run on interrupt + * @param requirements subsystems the action requires + */ +[[nodiscard]] CommandPtr RunEnd(std::function run, + std::function end, + std::initializer_list requirements); + +/** + * Constructs a command that runs an action every iteration until interrupted, + * and then runs a second action. + * + * @param run the action to run every iteration + * @param end the action to run on interrupt + * @param requirements subsystems the action requires + */ +[[nodiscard]] CommandPtr RunEnd(std::function run, + std::function end, + std::span requirements = {}); + +/** + * Constructs a command that prints a message and finishes. + * + * @param msg the message to print + */ +[[nodiscard]] CommandPtr Print(std::string_view msg); + +// Idling Commands + +/** + * Constructs a command that does nothing, finishing after a specified duration. + * + * @param duration after how long the command finishes + */ +[[nodiscard]] CommandPtr Wait(units::second_t duration); + +/** + * Constructs a command that does nothing, finishing once a command becomes + * true. + * + * @param condition the condition + */ +[[nodiscard]] CommandPtr WaitUntil(std::function condition); + +// Selector Commands + +/** + * Runs one of two commands, based on the boolean selector function. + * + * @param onTrue the command to run if the selector function returns true + * @param onFalse the command to run if the selector function returns false + * @param selector the selector function + */ +[[nodiscard]] CommandPtr Either(CommandPtr&& onTrue, CommandPtr&& onFalse, + std::function selector); + +/** + * Runs one of several commands, based on the selector function. + * + * @param selector the selector function + * @param commands map of commands to select from + */ +template +[[nodiscard]] CommandPtr Select( + std::function selector, + std::vector> commands); + +// Command Groups + +/** + * Runs a group of commands in series, one after the other. + */ +[[nodiscard]] CommandPtr Sequence(std::vector&& commands); + +/** + * Runs a group of commands in series, one after the other. Once the last + * command ends, the group is restarted. + */ +[[nodiscard]] CommandPtr RepeatingSequence(std::vector&& commands); + +/** + * Runs a group of commands at the same time. Ends once all commands in the + * group finish. + */ +[[nodiscard]] CommandPtr Parallel(std::vector&& commands); + +/** + * Runs a group of commands at the same time. Ends once any command in the group + * finishes, and cancels the others. + */ +[[nodiscard]] CommandPtr Race(std::vector&& commands); + +/** + * Runs a group of commands at the same time. Ends once a specific command + * finishes, and cancels the others. + */ +[[nodiscard]] CommandPtr Deadline(CommandPtr&& deadline, + std::vector&& others); +} // namespace cmd + +} // namespace frc2 diff --git a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/RobotDisabledCommandTest.java b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/RobotDisabledCommandTest.java index b807c71313..0914c25b8f 100644 --- a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/RobotDisabledCommandTest.java +++ b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/RobotDisabledCommandTest.java @@ -4,7 +4,7 @@ package edu.wpi.first.wpilibj2.command; -import static edu.wpi.first.wpilibj2.command.CommandGroupBase.parallel; +import static edu.wpi.first.wpilibj2.command.Commands.parallel; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue;