[commands] Move GroupedCommands to CommandScheduler (#4728)

Move the command group checking functionality from CommandGroupBase into CommandScheduler.
Update references to grouping as composition for clarity (because explicitly grouping isn't the only way to do it).
Deprecate the static factory methods parallel, race, and deadline in CommandGroupBase in favor of the identical ones in Commands.
This commit is contained in:
Starlight220
2022-12-07 07:13:31 +02:00
committed by GitHub
parent f18fd41ac3
commit 4bbdbdfb48
46 changed files with 450 additions and 472 deletions

View File

@@ -302,9 +302,9 @@ safe) semantics.
void Cancel();
/**
* Whether or not the command is currently scheduled. Note that this does not
* detect whether the command is being run by a CommandGroup, only whether it
* is directly being run by the scheduler.
* Whether or not the command is currently scheduled. Note that this does not
* detect whether the command is in a composition, only whether it is directly
* being run by the scheduler.
*
* @return Whether the command is scheduled.
*/
@@ -324,13 +324,32 @@ safe) semantics.
* Whether the command is currently grouped in a command group. Used as extra
* insurance to prevent accidental independent use of grouped commands.
*/
bool IsComposed() const;
/**
* Sets whether the command is currently composed in a command composition.
* Can be used to "reclaim" a command if a composition is no longer going to
* use it. NOT ADVISED!
*/
void SetComposed(bool isComposed);
/**
* Whether the command is currently grouped in a command group. Used as extra
* insurance to prevent accidental independent use of grouped commands.
*
* @deprecated Moved to IsComposed()
*/
WPI_DEPRECATED("Moved to IsComposed()")
bool IsGrouped() const;
/**
* Sets whether the command is currently grouped in a command group. Can be
* used to "reclaim" a command if a group is no longer going to use it. NOT
* ADVISED!
*
* @deprecated Moved to SetComposed()
*/
WPI_DEPRECATED("Moved to SetComposed()")
void SetGrouped(bool grouped);
/**
@@ -379,7 +398,7 @@ safe) semantics.
*/
virtual std::unique_ptr<Command> TransferOwnership() && = 0;
bool m_isGrouped = false;
bool m_isComposed = false;
};
/**

View File

@@ -4,61 +4,24 @@
#pragma once
#include <initializer_list>
#include <memory>
#include <span>
#include <vector>
#include <wpi/deprecated.h>
#include "frc2/command/CommandBase.h"
namespace frc2 {
/**
* A base for CommandGroups. Statically tracks commands that have been
* allocated to groups to ensure those commands are not also used independently,
* which can result in inconsistent command state and unpredictable execution.
* A base for CommandGroups.
*
* This class is provided by the NewCommands VendorDep
* @deprecated This class is an empty abstraction. Inherit directly from
* CommandBase.
*/
class CommandGroupBase : public CommandBase {
public:
/**
* Requires that the specified command not have been already allocated to a
* CommandGroup. Reports an error if the command is already grouped.
*
* @param command The command to check
* @return True if all the command is ungrouped.
*/
static bool RequireUngrouped(const Command& command);
/**
* Requires that the specified command not have been already allocated to a
* CommandGroup. Reports an error if the command is already grouped.
*
* @param command The command to check
* @return True if all the command is ungrouped.
*/
static bool RequireUngrouped(const Command* command);
/**
* Requires that the specified commands not have been already allocated to a
* CommandGroup. Reports an error if any of the commands are already grouped.
*
* @param commands The commands to check
* @return True if all the commands are ungrouped.
*/
static bool RequireUngrouped(
std::span<const std::unique_ptr<Command>> commands);
/**
* Requires that the specified commands not have been already allocated to a
* CommandGroup. Reports an error if any of the commands are already grouped.
*
* @param commands The commands to check
* @return True if all the commands are ungrouped.
*/
static bool RequireUngrouped(std::initializer_list<const Command*> commands);
/**
* Adds the given commands to the command group.
*

View File

@@ -252,8 +252,8 @@ class CommandPtr final {
/**
* Whether or not the command is currently scheduled. Note that this does not
* detect whether the command is being run by a CommandGroup, only whether it
* is directly being run by the scheduler.
* detect whether the command is in a composition, only whether it is directly
* being run by the scheduler.
*
* @return Whether the command is scheduled.
*/

View File

@@ -360,6 +360,34 @@ class CommandScheduler final : public nt::NTSendable,
*/
void OnCommandFinish(Action action);
/**
* Requires that the specified command hasn't been already added to a
* composition.
*
* @param command The command to check
* @throws if the given commands have already been composed.
*/
void RequireUngrouped(const Command* command);
/**
* Requires that the specified commands not have been already added to a
* composition.
*
* @param commands The commands to check
* @throws if the given commands have already been composed.
*/
void RequireUngrouped(std::span<const std::unique_ptr<Command>> commands);
/**
* Requires that the specified commands not have been already added to a
* composition.
*
* @param commands The commands to check
* @throws IllegalArgumentException if the given commands have already been
* composed.
*/
void RequireUngrouped(std::initializer_list<const Command*> commands);
void InitSendable(nt::NTSendableBuilder& builder) override;
private:

View File

@@ -9,25 +9,17 @@
#include <utility>
#include "frc2/command/CommandBase.h"
#include "frc2/command/CommandGroupBase.h"
#include "frc2/command/CommandHelper.h"
namespace frc2 {
/**
* Runs one of two commands, depending on the value of the given condition when
* this command is initialized. Does not actually schedule the selected command
* - rather, the command is run through this command; this ensures that the
* command will behave as expected if used as part of a CommandGroup. Requires
* the requirements of both commands, again to ensure proper functioning when
* used in a CommandGroup. If this is undesired, consider using
* ScheduleCommand.
* A command composition that runs one of two commands, depending on the value
* of the given condition when this command is initialized.
*
* <p>As this command contains multiple component commands within it, it is
* technically a command group; the command instances that are passed to it
* cannot be added to any other groups, or scheduled individually.
*
* <p>As a rule, CommandGroups require the union of the requirements of their
* component commands.
* <p>The rules for command compositions apply: command instances that are
* passed to it are owned by the composition and cannot be added to any other
* composition or scheduled individually, and the composition requires all
* subsystems its components require.
*
* This class is provided by the NewCommands VendorDep
*

View File

@@ -18,11 +18,13 @@
namespace frc2 {
/**
* A CommandGroup that runs a set of commands in parallel, ending when the last
* command ends.
* A command composition that runs a set of commands in parallel, ending when
* the last command ends.
*
* <p>As a rule, CommandGroups require the union of the requirements of their
* component commands.
* <p>The rules for command compositions apply: command instances that are
* passed to it are owned by the composition and cannot be added to any other
* composition or scheduled individually, and the composition requires all
* subsystems its components require.
*
* This class is provided by the NewCommands VendorDep
*/
@@ -30,23 +32,23 @@ class ParallelCommandGroup
: public CommandHelper<CommandGroupBase, ParallelCommandGroup> {
public:
/**
* Creates a new ParallelCommandGroup. The given commands will be executed
* Creates a new ParallelCommandGroup. The given commands will be executed
* simultaneously. The command group will finish when the last command
* finishes. If the CommandGroup is interrupted, only the commands that are
* finishes. If the composition is interrupted, only the commands that are
* still running will be interrupted.
*
* @param commands the commands to include in this group.
* @param commands the commands to include in this composition.
*/
explicit ParallelCommandGroup(
std::vector<std::unique_ptr<Command>>&& commands);
/**
* Creates a new ParallelCommandGroup. The given commands will be executed
* Creates a new ParallelCommandGroup. The given commands will be executed
* simultaneously. The command group will finish when the last command
* finishes. If the CommandGroup is interrupted, only the commands that are
* finishes. If the composition is interrupted, only the commands that are
* still running will be interrupted.
*
* @param commands the commands to include in this group.
* @param commands the commands to include in this composition.
*/
template <class... Types,
typename = std::enable_if_t<std::conjunction_v<

View File

@@ -18,12 +18,14 @@
namespace frc2 {
/**
* A CommandGroup that runs a set of commands in parallel, ending only when a
* specific command (the "deadline") ends, interrupting all other commands that
* are still running at that point.
* A command composition that runs a set of commands in parallel, ending only
* when a specific command (the "deadline") ends, interrupting all other
* commands that are still running at that point.
*
* <p>As a rule, CommandGroups require the union of the requirements of their
* component commands.
* <p>The rules for command compositions apply: command instances that are
* passed to it are owned by the composition and cannot be added to any other
* composition or scheduled individually, and the composition requires all
* subsystems its components require.
*
* This class is provided by the NewCommands VendorDep
*/
@@ -31,25 +33,25 @@ class ParallelDeadlineGroup
: public CommandHelper<CommandGroupBase, ParallelDeadlineGroup> {
public:
/**
* Creates a new ParallelDeadlineGroup. The given commands (including the
* deadline) will be executed simultaneously. The CommandGroup will finish
* when the deadline finishes, interrupting all other still-running commands.
* If the CommandGroup is interrupted, only the commands still running will be
* Creates a new ParallelDeadlineGroup. The given commands (including the
* deadline) will be executed simultaneously. The composition will finish when
* the deadline finishes, interrupting all other still-running commands. If
* the composition is interrupted, only the commands still running will be
* interrupted.
*
* @param deadline the command that determines when the group ends
* @param deadline the command that determines when the composition ends
* @param commands the commands to be executed
*/
ParallelDeadlineGroup(std::unique_ptr<Command>&& deadline,
std::vector<std::unique_ptr<Command>>&& commands);
/**
* Creates a new ParallelDeadlineGroup. The given commands (including the
* deadline) will be executed simultaneously. The CommandGroup will finish
* when the deadline finishes, interrupting all other still-running commands.
* If the CommandGroup is interrupted, only the commands still running will be
* Creates a new ParallelDeadlineGroup. The given commands (including the
* deadline) will be executed simultaneously. The composition will finish when
* the deadline finishes, interrupting all other still-running commands. If
* the composition is interrupted, only the commands still running will be
* interrupted.
*
* @param deadline the command that determines when the group ends
* @param deadline the command that determines when the composition ends
* @param commands the commands to be executed
*/
template <class T, class... Types,

View File

@@ -18,11 +18,13 @@
namespace frc2 {
/**
* A CommandGroup that runs a set of commands in parallel, ending when any one
* of the commands ends and interrupting all the others.
* A composition that runs a set of commands in parallel, ending when any one of
* the commands ends and interrupting all the others.
*
* <p>As a rule, CommandGroups require the union of the requirements of their
* component commands.
* <p>The rules for command compositions apply: command instances that are
* passed to it are owned by the composition and cannot be added to any other
* composition or scheduled individually, and the composition requires all
* subsystems its components require.
*
* This class is provided by the NewCommands VendorDep
*/
@@ -30,11 +32,11 @@ class ParallelRaceGroup
: public CommandHelper<CommandGroupBase, ParallelRaceGroup> {
public:
/**
* Creates a new ParallelCommandRace. The given commands will be executed
* Creates a new ParallelCommandRace. The given commands will be executed
* simultaneously, and will "race to the finish" - the first command to finish
* ends the entire command, with all other commands being interrupted.
*
* @param commands the commands to include in this group.
* @param commands the commands to include in this composition.
*/
explicit ParallelRaceGroup(std::vector<std::unique_ptr<Command>>&& commands);

View File

@@ -13,13 +13,12 @@
#include <utility>
#include "frc2/command/CommandBase.h"
#include "frc2/command/CommandGroupBase.h"
#include "frc2/command/CommandHelper.h"
namespace frc2 {
/**
* A command that runs another command in perpetuity, ignoring that command's
* end conditions. While this class does not extend {@link CommandGroupBase},
* end conditions. While this class does not extend frc2::CommandGroupBase,
* it is still considered a CommandGroup, as it allows one to compose another
* command within it; the command instances that are passed to it cannot be
* added to any other groups, or scheduled individually.

View File

@@ -13,19 +13,18 @@
#include <utility>
#include "frc2/command/CommandBase.h"
#include "frc2/command/CommandGroupBase.h"
#include "frc2/command/CommandHelper.h"
namespace frc2 {
/**
* A command that runs another command repeatedly, restarting it when it ends,
* until this command is interrupted. While this class does not extend {@link
* CommandGroupBase}, it is still considered a CommandGroup, as it allows one to
* compose another command within it; the command instances that are passed to
* it cannot be added to any other groups, or scheduled individually.
* until this command is interrupted. Command instances that are passed to it
* cannot be added to any other groups, or scheduled individually.
*
* <p>As a rule, CommandGroups require the union of the requirements of their
* component commands.
* <p>The rules for command compositions apply: command instances that are
* passed to it are owned by the composition and cannot be added to any other
* composition or scheduled individually, and the composition requires all
* subsystems its components require.
*
* <p>This class is provided by the NewCommands VendorDep
*/

View File

@@ -14,10 +14,10 @@
namespace frc2 {
/**
* Schedules the given commands when this command is initialized. Useful for
* forking off from CommandGroups. Note that if run from a CommandGroup, the
* group will not know about the status of the scheduled commands, and will
* treat this command as finishing instantly.
* Schedules the given commands when this command is initialized. Useful for
* forking off from CommandGroups. Note that if run from a composition, the
* composition will not know about the status of the scheduled commands, and
* will treat this command as finishing instantly.
*
* This class is provided by the NewCommands VendorDep
*/

View File

@@ -16,25 +16,18 @@
#include <vector>
#include "frc2/command/CommandBase.h"
#include "frc2/command/CommandGroupBase.h"
#include "frc2/command/PrintCommand.h"
namespace frc2 {
/**
* Runs one of a selection of commands, either using a selector and a key to
* command mapping, or a supplier that returns the command directly at runtime.
* Does not actually schedule the selected command - rather, the command is run
* through this command; this ensures that the command will behave as expected
* if used as part of a CommandGroup. Requires the requirements of all included
* commands, again to ensure proper functioning when used in a CommandGroup. If
* this is undesired, consider using ScheduleCommand.
* A command composition that runs one of a selection of commands, either using
* a selector and a key to command mapping, or a supplier that returns the
* command directly at runtime.
*
* <p>As this command contains multiple component commands within it, it is
* technically a command group; the command instances that are passed to it
* cannot be added to any other groups, or scheduled individually.
*
* <p>As a rule, CommandGroups require the union of the requirements of their
* component commands.
* <p>The rules for command compositions apply: command instances that are
* passed to it are owned by the composition and cannot be added to any other
* composition or scheduled individually, and the composition requires all
* subsystems its components require.
*
* This class is provided by the NewCommands VendorDep
*/
@@ -61,9 +54,7 @@ class SelectCommand : public CommandHelper<CommandBase, SelectCommand<Key>> {
...);
for (auto&& command : foo) {
if (!CommandGroupBase::RequireUngrouped(*command.second)) {
return;
}
CommandScheduler::GetInstance().RequireUngrouped(command.second.get());
}
for (auto&& command : foo) {
@@ -82,9 +73,7 @@ class SelectCommand : public CommandHelper<CommandBase, SelectCommand<Key>> {
std::vector<std::pair<Key, std::unique_ptr<Command>>>&& commands)
: m_selector{std::move(selector)} {
for (auto&& command : commands) {
if (!CommandGroupBase::RequireUngrouped(*command.second)) {
return;
}
CommandScheduler::GetInstance().RequireUngrouped(command.second.get());
}
for (auto&& command : commands) {

View File

@@ -24,10 +24,12 @@ namespace frc2 {
const size_t invalid_index = std::numeric_limits<size_t>::max();
/**
* A CommandGroups that runs a list of commands in sequence.
* A command composition that runs a list of commands in sequence.
*
* <p>As a rule, CommandGroups require the union of the requirements of their
* component commands.
* <p>The rules for command compositions apply: command instances that are
* passed to it are owned by the composition and cannot be added to any other
* composition or scheduled individually, and the composition requires all
* subsystems its components require.
*
* This class is provided by the NewCommands VendorDep
*/
@@ -35,21 +37,21 @@ class SequentialCommandGroup
: public CommandHelper<CommandGroupBase, SequentialCommandGroup> {
public:
/**
* Creates a new SequentialCommandGroup. The given commands will be run
* sequentially, with the CommandGroup finishing when the last command
* Creates a new SequentialCommandGroup. The given commands will be run
* sequentially, with the composition finishing when the last command
* finishes.
*
* @param commands the commands to include in this group.
* @param commands the commands to include in this composition.
*/
explicit SequentialCommandGroup(
std::vector<std::unique_ptr<Command>>&& commands);
/**
* Creates a new SequentialCommandGroup. The given commands will be run
* sequentially, with the CommandGroup finishing when the last command
* Creates a new SequentialCommandGroup. The given commands will be run
* sequentially, with the composition finishing when the last command
* finishes.
*
* @param commands the commands to include in this group.
* @param commands the commands to include in this composition.
*/
template <class... Types,
typename = std::enable_if_t<std::conjunction_v<

View File

@@ -13,7 +13,6 @@
#include <utility>
#include "frc2/command/CommandBase.h"
#include "frc2/command/CommandGroupBase.h"
#include "frc2/command/CommandHelper.h"
namespace frc2 {