Split the two command implementations into separate libraries (#2012)

This will allow us at the user code side to determine to include old commands, new commands or both.
This commit is contained in:
Thad House
2019-11-01 21:58:54 -07:00
committed by Peter Johnson
parent 2ad15cae19
commit 509819d83f
271 changed files with 470 additions and 91 deletions

View File

@@ -90,7 +90,6 @@
#include "frc/commands/PIDCommand.h"
#include "frc/commands/PIDSubsystem.h"
#include "frc/commands/PrintCommand.h"
#include "frc/commands/Scheduler.h"
#include "frc/commands/StartCommand.h"
#include "frc/commands/Subsystem.h"
#include "frc/commands/WaitCommand.h"

View File

@@ -1,73 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2011-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include "frc/buttons/Trigger.h"
#include "frc/commands/Command.h"
namespace frc {
/**
* This class provides an easy way to link commands to OI inputs.
*
* It is very easy to link a button to a command. For instance, you could link
* the trigger button of a joystick to a "score" command.
*
* This class represents a subclass of Trigger that is specifically aimed at
* buttons on an operator interface as a common use case of the more generalized
* Trigger objects. This is a simple wrapper around Trigger with the method
* names renamed to fit the Button object use.
*/
class Button : public Trigger {
public:
Button() = default;
Button(Button&&) = default;
Button& operator=(Button&&) = default;
/**
* Specifies the command to run when a button is first pressed.
*
* @param command The pointer to the command to run
*/
virtual void WhenPressed(Command* command);
/**
* Specifies the command to be scheduled while the button is pressed.
*
* The command will be scheduled repeatedly while the button is pressed and
* will be canceled when the button is released.
*
* @param command The pointer to the command to run
*/
virtual void WhileHeld(Command* command);
/**
* Specifies the command to run when the button is released.
*
* The command will be scheduled a single time.
*
* @param command The pointer to the command to run
*/
virtual void WhenReleased(Command* command);
/**
* Cancels the specificed command when the button is pressed.
*
* @param command The command to be canceled
*/
virtual void CancelWhenPressed(Command* command);
/**
* Toggle the specified command when the button is pressed.
*
* @param command The command to be toggled
*/
virtual void ToggleWhenPressed(Command* command);
};
} // namespace frc

View File

@@ -1,32 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2011-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
namespace frc {
class Trigger;
class Command;
class ButtonScheduler {
public:
ButtonScheduler(bool last, Trigger* button, Command* orders);
virtual ~ButtonScheduler() = default;
ButtonScheduler(ButtonScheduler&&) = default;
ButtonScheduler& operator=(ButtonScheduler&&) = default;
virtual void Execute() = 0;
void Start();
protected:
bool m_pressedLast;
Trigger* m_button;
Command* m_command;
};
} // namespace frc

View File

@@ -1,28 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2011-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include "frc/buttons/ButtonScheduler.h"
namespace frc {
class Trigger;
class Command;
class CancelButtonScheduler : public ButtonScheduler {
public:
CancelButtonScheduler(bool last, Trigger* button, Command* orders);
virtual ~CancelButtonScheduler() = default;
CancelButtonScheduler(CancelButtonScheduler&&) = default;
CancelButtonScheduler& operator=(CancelButtonScheduler&&) = default;
virtual void Execute();
};
} // namespace frc

View File

@@ -1,28 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2011-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include "frc/buttons/ButtonScheduler.h"
namespace frc {
class Trigger;
class Command;
class HeldButtonScheduler : public ButtonScheduler {
public:
HeldButtonScheduler(bool last, Trigger* button, Command* orders);
virtual ~HeldButtonScheduler() = default;
HeldButtonScheduler(HeldButtonScheduler&&) = default;
HeldButtonScheduler& operator=(HeldButtonScheduler&&) = default;
virtual void Execute();
};
} // namespace frc

View File

@@ -1,33 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2011-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include "frc/buttons/Button.h"
namespace frc {
class InternalButton : public Button {
public:
InternalButton() = default;
explicit InternalButton(bool inverted);
virtual ~InternalButton() = default;
InternalButton(InternalButton&&) = default;
InternalButton& operator=(InternalButton&&) = default;
void SetInverted(bool inverted);
void SetPressed(bool pressed);
virtual bool Get();
private:
bool m_pressed = false;
bool m_inverted = false;
};
} // namespace frc

View File

@@ -1,30 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2011-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include "frc/GenericHID.h"
#include "frc/buttons/Button.h"
namespace frc {
class JoystickButton : public Button {
public:
JoystickButton(GenericHID* joystick, int buttonNumber);
virtual ~JoystickButton() = default;
JoystickButton(JoystickButton&&) = default;
JoystickButton& operator=(JoystickButton&&) = default;
virtual bool Get();
private:
GenericHID* m_joystick;
int m_buttonNumber;
};
} // namespace frc

View File

@@ -1,36 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2011-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <memory>
#include <networktables/NetworkTable.h>
#include <networktables/NetworkTableEntry.h>
#include <wpi/Twine.h>
#include "frc/buttons/Button.h"
namespace frc {
class NetworkButton : public Button {
public:
NetworkButton(const wpi::Twine& tableName, const wpi::Twine& field);
NetworkButton(std::shared_ptr<nt::NetworkTable> table,
const wpi::Twine& field);
virtual ~NetworkButton() = default;
NetworkButton(NetworkButton&&) = default;
NetworkButton& operator=(NetworkButton&&) = default;
virtual bool Get();
private:
nt::NetworkTableEntry m_entry;
};
} // namespace frc

View File

@@ -1,36 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include "frc/GenericHID.h"
#include "frc/buttons/Button.h"
namespace frc {
class POVButton : public Button {
public:
/**
* Creates a POV button for triggering commands.
*
* @param joystick The GenericHID object that has the POV
* @param angle The desired angle in degrees (e.g. 90, 270)
* @param povNumber The POV number (@see GenericHID#GetPOV)
*/
POVButton(GenericHID& joystick, int angle, int povNumber = 0);
virtual ~POVButton() = default;
POVButton(POVButton&&) = default;
POVButton& operator=(POVButton&&) = default;
bool Get() override;
private:
GenericHID* m_joystick;
int m_angle;
int m_povNumber;
};
} // namespace frc

View File

@@ -1,28 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2011-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include "frc/buttons/ButtonScheduler.h"
namespace frc {
class Trigger;
class Command;
class PressedButtonScheduler : public ButtonScheduler {
public:
PressedButtonScheduler(bool last, Trigger* button, Command* orders);
virtual ~PressedButtonScheduler() = default;
PressedButtonScheduler(PressedButtonScheduler&&) = default;
PressedButtonScheduler& operator=(PressedButtonScheduler&&) = default;
virtual void Execute();
};
} // namespace frc

View File

@@ -1,28 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2011-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include "frc/buttons/ButtonScheduler.h"
namespace frc {
class Trigger;
class Command;
class ReleasedButtonScheduler : public ButtonScheduler {
public:
ReleasedButtonScheduler(bool last, Trigger* button, Command* orders);
virtual ~ReleasedButtonScheduler() = default;
ReleasedButtonScheduler(ReleasedButtonScheduler&&) = default;
ReleasedButtonScheduler& operator=(ReleasedButtonScheduler&&) = default;
virtual void Execute();
};
} // namespace frc

View File

@@ -1,28 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2011-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include "frc/buttons/ButtonScheduler.h"
namespace frc {
class Trigger;
class Command;
class ToggleButtonScheduler : public ButtonScheduler {
public:
ToggleButtonScheduler(bool last, Trigger* button, Command* orders);
virtual ~ToggleButtonScheduler() = default;
ToggleButtonScheduler(ToggleButtonScheduler&&) = default;
ToggleButtonScheduler& operator=(ToggleButtonScheduler&&) = default;
virtual void Execute();
};
} // namespace frc

View File

@@ -1,56 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2011-2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <atomic>
#include "frc/smartdashboard/Sendable.h"
#include "frc/smartdashboard/SendableHelper.h"
namespace frc {
class Command;
/**
* This class provides an easy way to link commands to inputs.
*
* It is very easy to link a polled input to a command. For instance, you could
* link the trigger button of a joystick to a "score" command or an encoder
* reaching a particular value.
*
* It is encouraged that teams write a subclass of Trigger if they want to have
* something unusual (for instance, if they want to react to the user holding
* a button while the robot is reading a certain sensor input). For this, they
* only have to write the {@link Trigger#Get()} method to get the full
* functionality of the Trigger class.
*/
class Trigger : public Sendable, public SendableHelper<Trigger> {
public:
Trigger() = default;
~Trigger() override = default;
Trigger(const Trigger& rhs);
Trigger& operator=(const Trigger& rhs);
Trigger(Trigger&& rhs);
Trigger& operator=(Trigger&& rhs);
bool Grab();
virtual bool Get() = 0;
void WhenActive(Command* command);
void WhileActive(Command* command);
void WhenInactive(Command* command);
void CancelWhenActive(Command* command);
void ToggleWhenActive(Command* command);
void InitSendable(SendableBuilder& builder) override;
private:
std::atomic_bool m_sendablePressed{false};
};
} // namespace frc

View File

@@ -1,492 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2011-2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <memory>
#include <string>
#include <wpi/SmallPtrSet.h>
#include <wpi/Twine.h>
#include "frc/ErrorBase.h"
#include "frc/commands/Subsystem.h"
#include "frc/smartdashboard/Sendable.h"
#include "frc/smartdashboard/SendableHelper.h"
namespace frc {
class CommandGroup;
/**
* The Command class is at the very core of the entire command framework.
*
* Every command can be started with a call to Start(). Once a command is
* started it will call Initialize(), and then will repeatedly call Execute()
* until the IsFinished() returns true. Once it does,End() will be called.
*
* However, if at any point while it is running Cancel() is called, then the
* command will be stopped and Interrupted() will be called.
*
* If a command uses a Subsystem, then it should specify that it does so by
* calling the Requires() method in its constructor. Note that a Command may
* have multiple requirements, and Requires() should be called for each one.
*
* If a command is running and a new command with shared requirements is
* started, then one of two things will happen. If the active command is
* interruptible, then Cancel() will be called and the command will be removed
* to make way for the new one. If the active command is not interruptible, the
* other one will not even be started, and the active one will continue
* functioning.
*
* @see CommandGroup
* @see Subsystem
*/
class Command : public ErrorBase,
public Sendable,
public SendableHelper<Command> {
friend class CommandGroup;
friend class Scheduler;
public:
/**
* Creates a new command.
*
* The name of this command will be default.
*/
Command();
/**
* Creates a new command with the given name and no timeout.
*
* @param name the name for this command
*/
explicit Command(const wpi::Twine& name);
/**
* Creates a new command with the given timeout and a default name.
*
* @param timeout the time (in seconds) before this command "times out"
* @see IsTimedOut()
*/
explicit Command(double timeout);
/**
* Creates a new command with the given timeout and a default name.
*
* @param subsystem the subsystem that the command requires
*/
explicit Command(Subsystem& subsystem);
/**
* Creates a new command with the given name and timeout.
*
* @param name the name of the command
* @param timeout the time (in seconds) before this command "times out"
* @see IsTimedOut()
*/
Command(const wpi::Twine& name, double timeout);
/**
* Creates a new command with the given name and timeout.
*
* @param name the name of the command
* @param subsystem the subsystem that the command requires
*/
Command(const wpi::Twine& name, Subsystem& subsystem);
/**
* Creates a new command with the given name and timeout.
*
* @param timeout the time (in seconds) before this command "times out"
* @param subsystem the subsystem that the command requires @see IsTimedOut()
*/
Command(double timeout, Subsystem& subsystem);
/**
* Creates a new command with the given name and timeout.
*
* @param name the name of the command
* @param timeout the time (in seconds) before this command "times out"
* @param subsystem the subsystem that the command requires @see IsTimedOut()
*/
Command(const wpi::Twine& name, double timeout, Subsystem& subsystem);
~Command() override = default;
Command(Command&&) = default;
Command& operator=(Command&&) = default;
/**
* Returns the time since this command was initialized (in seconds).
*
* This function will work even if there is no specified timeout.
*
* @return the time since this command was initialized (in seconds).
*/
double TimeSinceInitialized() const;
/**
* This method specifies that the given Subsystem is used by this command.
*
* This method is crucial to the functioning of the Command System in general.
*
* Note that the recommended way to call this method is in the constructor.
*
* @param subsystem The Subsystem required
* @see Subsystem
*/
void Requires(Subsystem* s);
/**
* Starts up the command. Gets the command ready to start.
*
* Note that the command will eventually start, however it will not
* necessarily do so immediately, and may in fact be canceled before
* initialize is even called.
*/
void Start();
/**
* The run method is used internally to actually run the commands.
*
* @return Whether or not the command should stay within the Scheduler.
*/
bool Run();
/**
* This will cancel the current command.
*
* This will cancel the current command eventually. It can be called multiple
* times. And it can be called when the command is not running. If the command
* is running though, then the command will be marked as canceled and
* eventually removed.
*
* A command can not be canceled if it is a part of a command group, you must
* cancel the command group instead.
*/
void Cancel();
/**
* Returns whether or not the command is running.
*
* This may return true even if the command has just been canceled, as it may
* not have yet called Interrupted().
*
* @return whether or not the command is running
*/
bool IsRunning() const;
/**
* Returns whether or not the command has been initialized.
*
* @return whether or not the command has been initialized.
*/
bool IsInitialized() const;
/**
* Returns whether or not the command has completed running.
*
* @return whether or not the command has completed running.
*/
bool IsCompleted() const;
/**
* Returns whether or not this has been canceled.
*
* @return whether or not this has been canceled
*/
bool IsCanceled() const;
/**
* Returns whether or not this command can be interrupted.
*
* @return whether or not this command can be interrupted
*/
bool IsInterruptible() const;
/**
* Sets whether or not this command can be interrupted.
*
* @param interruptible whether or not this command can be interrupted
*/
void SetInterruptible(bool interruptible);
/**
* Checks if the command requires the given Subsystem.
*
* @param system the system
* @return whether or not the subsystem is required (false if given nullptr)
*/
bool DoesRequire(Subsystem* subsystem) const;
using SubsystemSet = wpi::SmallPtrSetImpl<Subsystem*>;
/**
* Returns the requirements (as an std::set of Subsystem pointers) of this
* command.
*
* @return The requirements (as an std::set of Subsystem pointers) of this
* command
*/
const SubsystemSet& GetRequirements() const;
/**
* Returns the CommandGroup that this command is a part of.
*
* Will return null if this Command is not in a group.
*
* @return The CommandGroup that this command is a part of (or null if not in
* group)
*/
CommandGroup* GetGroup() const;
/**
* Sets whether or not this Command should run when the robot is disabled.
*
* By default a command will not run when the robot is disabled, and will in
* fact be canceled.
*
* @param run Whether this command should run when the robot is disabled.
*/
void SetRunWhenDisabled(bool run);
/**
* Returns whether or not this Command will run when the robot is disabled, or
* if it will cancel itself.
*
* @return Whether this Command will run when the robot is disabled, or if it
* will cancel itself.
*/
bool WillRunWhenDisabled() const;
/**
* Get the ID (sequence number) for this command.
*
* The ID is a unique sequence number that is incremented for each command.
*
* @return The ID of this command
*/
int GetID() const;
protected:
/**
* Sets the timeout of this command.
*
* @param timeout the timeout (in seconds)
* @see IsTimedOut()
*/
void SetTimeout(double timeout);
/**
* Returns whether or not the TimeSinceInitialized() method returns a number
* which is greater than or equal to the timeout for the command.
*
* If there is no timeout, this will always return false.
*
* @return whether the time has expired
*/
bool IsTimedOut() const;
/**
* If changes are locked, then this will generate a CommandIllegalUse error.
*
* @param message The message to report on error (it is appended by a default
* message)
* @return True if assert passed, false if assert failed.
*/
bool AssertUnlocked(const std::string& message);
/**
* Sets the parent of this command. No actual change is made to the group.
*
* @param parent the parent
*/
void SetParent(CommandGroup* parent);
/**
* Returns whether the command has a parent.
*
* @param True if the command has a parent.
*/
bool IsParented() const;
/**
* Clears list of subsystem requirements.
*
* This is only used by ConditionalCommand so cancelling the chosen command
* works properly in CommandGroup.
*/
void ClearRequirements();
/**
* The initialize method is called the first time this Command is run after
* being started.
*/
virtual void Initialize();
/**
* The execute method is called repeatedly until this Command either finishes
* or is canceled.
*/
virtual void Execute();
/**
* Returns whether this command is finished.
*
* If it is, then the command will be removed and End() will be called.
*
* It may be useful for a team to reference the IsTimedOut() method for
* time-sensitive commands.
*
* Returning false will result in the command never ending automatically.
* It may still be cancelled manually or interrupted by another command.
* Returning true will result in the command executing once and finishing
* immediately. We recommend using InstantCommand for this.
*
* @return Whether this command is finished.
* @see IsTimedOut()
*/
virtual bool IsFinished() = 0;
/**
* Called when the command ended peacefully.
*
* This is where you may want to wrap up loose ends, like shutting off a motor
* that was being used in the command.
*/
virtual void End();
/**
* Called when the command ends because somebody called Cancel() or another
* command shared the same requirements as this one, and booted it out.
*
* This is where you may want to wrap up loose ends, like shutting off a motor
* that was being used in the command.
*
* Generally, it is useful to simply call the End() method within this method,
* as done here.
*/
virtual void Interrupted();
virtual void _Initialize();
virtual void _Interrupted();
virtual void _Execute();
virtual void _End();
/**
* This works like Cancel(), except that it doesn't throw an exception if it
* is a part of a command group.
*
* Should only be called by the parent command group.
*/
virtual void _Cancel();
friend class ConditionalCommand;
/**
* Gets the name of this Command.
*
* @return Name
*/
std::string GetName() const;
/**
* Sets the name of this Command.
*
* @param name name
*/
void SetName(const wpi::Twine& name);
/**
* Gets the subsystem name of this Command.
*
* @return Subsystem name
*/
std::string GetSubsystem() const;
/**
* Sets the subsystem name of this Command.
*
* @param subsystem subsystem name
*/
void SetSubsystem(const wpi::Twine& subsystem);
private:
/**
* Prevents further changes from being made.
*/
void LockChanges();
/**
* Called when the command has been removed.
*
* This will call Interrupted() or End().
*/
void Removed();
/**
* This is used internally to mark that the command has been started.
*
* The lifecycle of a command is:
*
* StartRunning() is called. Run() is called (multiple times potentially).
* Removed() is called.
*
* It is very important that StartRunning() and Removed() be called in order
* or some assumptions of the code will be broken.
*/
void StartRunning();
/**
* Called to indicate that the timer should start.
*
* This is called right before Initialize() is, inside the Run() method.
*/
void StartTiming();
// The time since this command was initialized
double m_startTime = -1;
// The time (in seconds) before this command "times out" (-1 if no timeout)
double m_timeout;
// Whether or not this command has been initialized
bool m_initialized = false;
// The requirements (or null if no requirements)
wpi::SmallPtrSet<Subsystem*, 4> m_requirements;
// Whether or not it is running
bool m_running = false;
// Whether or not it is interruptible
bool m_interruptible = true;
// Whether or not it has been canceled
bool m_canceled = false;
// Whether or not it has been locked
bool m_locked = false;
// Whether this command should run when the robot is disabled
bool m_runWhenDisabled = false;
// The CommandGroup this is in
CommandGroup* m_parent = nullptr;
// Whether or not this command has completed running
bool m_completed = false;
int m_commandID = m_commandCounter++;
static int m_commandCounter;
public:
void InitSendable(SendableBuilder& builder) override;
};
} // namespace frc

View File

@@ -1,180 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2011-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <vector>
#include <wpi/Twine.h>
#include "frc/commands/Command.h"
#include "frc/commands/CommandGroupEntry.h"
namespace frc {
/**
* A CommandGroup is a list of commands which are executed in sequence.
*
* Commands in a CommandGroup are added using the AddSequential() method and are
* called sequentially. CommandGroups are themselves Commands and can be given
* to other CommandGroups.
*
* CommandGroups will carry all of the requirements of their Command
* subcommands. Additional requirements can be specified by calling Requires()
* normally in the constructor.
*
* CommandGroups can also execute commands in parallel, simply by adding them
* using AddParallel().
*
* @see Command
* @see Subsystem
*/
class CommandGroup : public Command {
public:
CommandGroup() = default;
/**
* Creates a new CommandGroup with the given name.
*
* @param name The name for this command group
*/
explicit CommandGroup(const wpi::Twine& name);
virtual ~CommandGroup() = default;
CommandGroup(CommandGroup&&) = default;
CommandGroup& operator=(CommandGroup&&) = default;
/**
* Adds a new Command to the group. The Command will be started after all the
* previously added Commands.
*
* Note that any requirements the given Command has will be added to the
* group. For this reason, a Command's requirements can not be changed after
* being added to a group.
*
* It is recommended that this method be called in the constructor.
*
* @param command The Command to be added
*/
void AddSequential(Command* command);
/**
* Adds a new Command to the group with a given timeout. The Command will be
* started after all the previously added commands.
*
* Once the Command is started, it will be run until it finishes or the time
* expires, whichever is sooner. Note that the given Command will have no
* knowledge that it is on a timer.
*
* Note that any requirements the given Command has will be added to the
* group. For this reason, a Command's requirements can not be changed after
* being added to a group.
*
* It is recommended that this method be called in the constructor.
*
* @param command The Command to be added
* @param timeout The timeout (in seconds)
*/
void AddSequential(Command* command, double timeout);
/**
* Adds a new child Command to the group. The Command will be started after
* all the previously added Commands.
*
* Instead of waiting for the child to finish, a CommandGroup will have it run
* at the same time as the subsequent Commands. The child will run until
* either it finishes, a new child with conflicting requirements is started,
* or the main sequence runs a Command with conflicting requirements. In the
* latter two cases, the child will be canceled even if it says it can't be
* interrupted.
*
* Note that any requirements the given Command has will be added to the
* group. For this reason, a Command's requirements can not be changed after
* being added to a group.
*
* It is recommended that this method be called in the constructor.
*
* @param command The command to be added
*/
void AddParallel(Command* command);
/**
* Adds a new child Command to the group with the given timeout. The Command
* will be started after all the previously added Commands.
*
* Once the Command is started, it will run until it finishes, is interrupted,
* or the time expires, whichever is sooner. Note that the given Command will
* have no knowledge that it is on a timer.
*
* Instead of waiting for the child to finish, a CommandGroup will have it run
* at the same time as the subsequent Commands. The child will run until
* either it finishes, the timeout expires, a new child with conflicting
* requirements is started, or the main sequence runs a Command with
* conflicting requirements. In the latter two cases, the child will be
* canceled even if it says it can't be interrupted.
*
* Note that any requirements the given Command has will be added to the
* group. For this reason, a Command's requirements can not be changed after
* being added to a group.
*
* It is recommended that this method be called in the constructor.
*
* @param command The command to be added
* @param timeout The timeout (in seconds)
*/
void AddParallel(Command* command, double timeout);
bool IsInterruptible() const;
int GetSize() const;
protected:
/**
* Can be overridden by teams.
*/
virtual void Initialize();
/**
* Can be overridden by teams.
*/
virtual void Execute();
/**
* Can be overridden by teams.
*/
virtual bool IsFinished();
/**
* Can be overridden by teams.
*/
virtual void End();
/**
* Can be overridden by teams.
*/
virtual void Interrupted();
virtual void _Initialize();
virtual void _Execute();
virtual void _End();
virtual void _Interrupted();
private:
void CancelConflicts(Command* command);
// The commands in this group (stored in entries)
std::vector<CommandGroupEntry> m_commands;
// The active children in this group (stored in entries)
std::vector<CommandGroupEntry*> m_children;
// The current command, -1 signifies that none have been run
int m_currentCommandIndex = -1;
};
} // namespace frc

View File

@@ -1,35 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2011-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
namespace frc {
class Command;
class CommandGroupEntry {
public:
enum Sequence {
kSequence_InSequence,
kSequence_BranchPeer,
kSequence_BranchChild
};
CommandGroupEntry() = default;
CommandGroupEntry(Command* command, Sequence state, double timeout = -1.0);
CommandGroupEntry(CommandGroupEntry&&) = default;
CommandGroupEntry& operator=(CommandGroupEntry&&) = default;
bool IsTimedOut() const;
double m_timeout = -1.0;
Command* m_command = nullptr;
Sequence m_state = kSequence_InSequence;
};
} // namespace frc

View File

@@ -1,84 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2017-2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <wpi/Twine.h>
#include "frc/commands/Command.h"
namespace frc {
/**
* A ConditionalCommand is a Command that starts one of two commands.
*
* A ConditionalCommand uses the Condition method to determine whether it should
* run onTrue or onFalse.
*
* A ConditionalCommand adds the proper Command to the Scheduler during
* Initialize() and then IsFinished() will return true once that Command has
* finished executing.
*
* If no Command is specified for onFalse, the occurrence of that condition
* will be a no-op.
*
* A ConditionalCommand will require the superset of subsystems of the onTrue
* and onFalse commands.
*
* @see Command
* @see Scheduler
*/
class ConditionalCommand : public Command {
public:
/**
* Creates a new ConditionalCommand with given onTrue and onFalse Commands.
*
* @param onTrue The Command to execute if Condition() returns true
* @param onFalse The Command to execute if Condition() returns false
*/
explicit ConditionalCommand(Command* onTrue, Command* onFalse = nullptr);
/**
* Creates a new ConditionalCommand with given onTrue and onFalse Commands.
*
* @param name The name for this command group
* @param onTrue The Command to execute if Condition() returns true
* @param onFalse The Command to execute if Condition() returns false
*/
ConditionalCommand(const wpi::Twine& name, Command* onTrue,
Command* onFalse = nullptr);
virtual ~ConditionalCommand() = default;
ConditionalCommand(ConditionalCommand&&) = default;
ConditionalCommand& operator=(ConditionalCommand&&) = default;
protected:
/**
* The Condition to test to determine which Command to run.
*
* @return true if m_onTrue should be run or false if m_onFalse should be run.
*/
virtual bool Condition() = 0;
void _Initialize() override;
void _Cancel() override;
bool IsFinished() override;
void _Interrupted() override;
private:
// The Command to execute if Condition() returns true
Command* m_onTrue;
// The Command to execute if Condition() returns false
Command* m_onFalse;
// Stores command chosen by condition
Command* m_chosenCommand = nullptr;
};
} // namespace frc

View File

@@ -1,93 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <functional>
#include <wpi/Twine.h>
#include "frc/commands/Command.h"
#include "frc/commands/Subsystem.h"
namespace frc {
/**
* This command will execute once, then finish immediately afterward.
*
* Subclassing InstantCommand is shorthand for returning true from IsFinished().
*/
class InstantCommand : public Command {
public:
/**
* Creates a new InstantCommand with the given name.
*
* @param name The name for this command
*/
explicit InstantCommand(const wpi::Twine& name);
/**
* Creates a new InstantCommand with the given requirement.
*
* @param subsystem The subsystem that the command requires
*/
explicit InstantCommand(Subsystem& subsystem);
/**
* Creates a new InstantCommand with the given name.
*
* @param name The name for this command
* @param subsystem The subsystem that the command requires
*/
InstantCommand(const wpi::Twine& name, Subsystem& subsystem);
/**
* Create a command that calls the given function when run.
*
* @param func The function to run when Initialize() is run.
*/
explicit InstantCommand(std::function<void()> func);
/**
* Create a command that calls the given function when run.
*
* @param subsystem The subsystems that this command runs on.
* @param func The function to run when Initialize() is run.
*/
InstantCommand(Subsystem& subsystem, std::function<void()> func);
/**
* Create a command that calls the given function when run.
*
* @param name The name of the command.
* @param func The function to run when Initialize() is run.
*/
InstantCommand(const wpi::Twine& name, std::function<void()> func);
/**
* Create a command that calls the given function when run.
*
* @param name The name of the command.
* @param subsystem The subsystems that this command runs on.
* @param func The function to run when Initialize() is run.
*/
InstantCommand(const wpi::Twine& name, Subsystem& subsystem,
std::function<void()> func);
InstantCommand() = default;
virtual ~InstantCommand() = default;
InstantCommand(InstantCommand&&) = default;
InstantCommand& operator=(InstantCommand&&) = default;
protected:
std::function<void()> m_func = nullptr;
void _Initialize() override;
bool IsFinished() override;
};
} // namespace frc

View File

@@ -1,74 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2011-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <memory>
#include <wpi/Twine.h>
#include "frc/PIDController.h"
#include "frc/PIDOutput.h"
#include "frc/PIDSource.h"
#include "frc/commands/Command.h"
namespace frc {
class PIDCommand : public Command, public PIDOutput, public PIDSource {
public:
PIDCommand(const wpi::Twine& name, double p, double i, double d);
PIDCommand(const wpi::Twine& name, double p, double i, double d,
double period);
PIDCommand(const wpi::Twine& name, double p, double i, double d, double f,
double period);
PIDCommand(double p, double i, double d);
PIDCommand(double p, double i, double d, double period);
PIDCommand(double p, double i, double d, double f, double period);
PIDCommand(const wpi::Twine& name, double p, double i, double d,
Subsystem& subsystem);
PIDCommand(const wpi::Twine& name, double p, double i, double d,
double period, Subsystem& subsystem);
PIDCommand(const wpi::Twine& name, double p, double i, double d, double f,
double period, Subsystem& subsystem);
PIDCommand(double p, double i, double d, Subsystem& subsystem);
PIDCommand(double p, double i, double d, double period, Subsystem& subsystem);
PIDCommand(double p, double i, double d, double f, double period,
Subsystem& subsystem);
virtual ~PIDCommand() = default;
PIDCommand(PIDCommand&&) = default;
PIDCommand& operator=(PIDCommand&&) = default;
void SetSetpointRelative(double deltaSetpoint);
// PIDOutput interface
void PIDWrite(double output) override;
// PIDSource interface
double PIDGet() override;
protected:
std::shared_ptr<PIDController> GetPIDController() const;
void _Initialize() override;
void _Interrupted() override;
void _End() override;
void SetSetpoint(double setpoint);
double GetSetpoint() const;
double GetPosition();
virtual double ReturnPIDInput() = 0;
virtual void UsePIDOutput(double output) = 0;
private:
// The internal PIDController
std::shared_ptr<PIDController> m_controller;
public:
void InitSendable(SendableBuilder& builder) override;
};
} // namespace frc

View File

@@ -1,236 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2011-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <memory>
#include <wpi/Twine.h>
#include "frc/PIDController.h"
#include "frc/PIDOutput.h"
#include "frc/PIDSource.h"
#include "frc/commands/Subsystem.h"
namespace frc {
/**
* This class is designed to handle the case where there is a Subsystem which
* uses a single PIDController almost constantly (for instance, an elevator
* which attempts to stay at a constant height).
*
* It provides some convenience methods to run an internal PIDController. It
* also allows access to the internal PIDController in order to give total
* control to the programmer.
*/
class PIDSubsystem : public Subsystem, public PIDOutput, public PIDSource {
public:
/**
* Instantiates a PIDSubsystem that will use the given P, I, and D values.
*
* @param name the name
* @param p the proportional value
* @param i the integral value
* @param d the derivative value
*/
PIDSubsystem(const wpi::Twine& name, double p, double i, double d);
/**
* Instantiates a PIDSubsystem that will use the given P, I, and D values.
*
* @param name the name
* @param p the proportional value
* @param i the integral value
* @param d the derivative value
* @param f the feedforward value
*/
PIDSubsystem(const wpi::Twine& name, double p, double i, double d, double f);
/**
* Instantiates a PIDSubsystem that will use the given P, I, and D values.
*
* It will also space the time between PID loop calculations to be equal to
* the given period.
*
* @param name the name
* @param p the proportional value
* @param i the integral value
* @param d the derivative value
* @param f the feedfoward value
* @param period the time (in seconds) between calculations
*/
PIDSubsystem(const wpi::Twine& name, double p, double i, double d, double f,
double period);
/**
* Instantiates a PIDSubsystem that will use the given P, I, and D values.
*
* It will use the class name as its name.
*
* @param p the proportional value
* @param i the integral value
* @param d the derivative value
*/
PIDSubsystem(double p, double i, double d);
/**
* Instantiates a PIDSubsystem that will use the given P, I, and D values.
*
* It will use the class name as its name.
*
* @param p the proportional value
* @param i the integral value
* @param d the derivative value
* @param f the feedforward value
*/
PIDSubsystem(double p, double i, double d, double f);
/**
* Instantiates a PIDSubsystem that will use the given P, I, and D values.
*
* It will use the class name as its name. It will also space the time
* between PID loop calculations to be equal to the given period.
*
* @param p the proportional value
* @param i the integral value
* @param d the derivative value
* @param f the feedforward value
* @param period the time (in seconds) between calculations
*/
PIDSubsystem(double p, double i, double d, double f, double period);
~PIDSubsystem() override = default;
PIDSubsystem(PIDSubsystem&&) = default;
PIDSubsystem& operator=(PIDSubsystem&&) = default;
/**
* Enables the internal PIDController.
*/
void Enable();
/**
* Disables the internal PIDController.
*/
void Disable();
// PIDOutput interface
void PIDWrite(double output) override;
// PIDSource interface
double PIDGet() override;
/**
* Sets the setpoint to the given value.
*
* If SetRange() was called, then the given setpoint will be trimmed to fit
* within the range.
*
* @param setpoint the new setpoint
*/
void SetSetpoint(double setpoint);
/**
* Adds the given value to the setpoint.
*
* If SetRange() was used, then the bounds will still be honored by this
* method.
*
* @param deltaSetpoint the change in the setpoint
*/
void SetSetpointRelative(double deltaSetpoint);
/**
* Sets the maximum and minimum values expected from the input.
*
* @param minimumInput the minimum value expected from the input
* @param maximumInput the maximum value expected from the output
*/
void SetInputRange(double minimumInput, double maximumInput);
/**
* Sets the maximum and minimum values to write.
*
* @param minimumOutput the minimum value to write to the output
* @param maximumOutput the maximum value to write to the output
*/
void SetOutputRange(double minimumOutput, double maximumOutput);
/**
* Return the current setpoint.
*
* @return The current setpoint
*/
double GetSetpoint();
/**
* Returns the current position.
*
* @return the current position
*/
double GetPosition();
/**
* Returns the current rate.
*
* @return the current rate
*/
double GetRate();
/**
* Set the absolute error which is considered tolerable for use with
* OnTarget.
*
* @param absValue absolute error which is tolerable
*/
virtual void SetAbsoluteTolerance(double absValue);
/**
* Set the percentage error which is considered tolerable for use with
* OnTarget().
*
* @param percent percentage error which is tolerable
*/
virtual void SetPercentTolerance(double percent);
/**
* Return true if the error is within the percentage of the total input range,
* determined by SetTolerance().
*
* This asssumes that the maximum and minimum input were set using SetInput().
* Use OnTarget() in the IsFinished() method of commands that use this
* subsystem.
*
* Currently this just reports on target as the actual value passes through
* the setpoint. Ideally it should be based on being within the tolerance for
* some period of time.
*
* @return True if the error is within the percentage tolerance of the input
* range
*/
virtual bool OnTarget() const;
protected:
/**
* Returns the PIDController used by this PIDSubsystem.
*
* Use this if you would like to fine tune the PID loop.
*
* @return The PIDController used by this PIDSubsystem
*/
std::shared_ptr<PIDController> GetPIDController();
virtual double ReturnPIDInput() = 0;
virtual void UsePIDOutput(double output) = 0;
private:
// The internal PIDController
std::shared_ptr<PIDController> m_controller;
};
} // namespace frc

View File

@@ -1,33 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2011-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <string>
#include <wpi/Twine.h>
#include "frc/commands/InstantCommand.h"
namespace frc {
class PrintCommand : public InstantCommand {
public:
explicit PrintCommand(const wpi::Twine& message);
virtual ~PrintCommand() = default;
PrintCommand(PrintCommand&&) = default;
PrintCommand& operator=(PrintCommand&&) = default;
protected:
virtual void Initialize();
private:
std::string m_message;
};
} // namespace frc

View File

@@ -1,100 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2011-2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <memory>
#include "frc/ErrorBase.h"
#include "frc/smartdashboard/Sendable.h"
#include "frc/smartdashboard/SendableHelper.h"
namespace frc {
class ButtonScheduler;
class Command;
class Subsystem;
class Scheduler : public ErrorBase,
public Sendable,
public SendableHelper<Scheduler> {
public:
/**
* Returns the Scheduler, creating it if one does not exist.
*
* @return the Scheduler
*/
static Scheduler* GetInstance();
/**
* Add a command to be scheduled later.
*
* In any pass through the scheduler, all commands are added to the additions
* list, then at the end of the pass, they are all scheduled.
*
* @param command The command to be scheduled
*/
void AddCommand(Command* command);
void AddButton(ButtonScheduler* button);
/**
* Registers a Subsystem to this Scheduler, so that the Scheduler might know
* if a default Command needs to be run.
*
* All Subsystems should call this.
*
* @param system the system
*/
void RegisterSubsystem(Subsystem* subsystem);
/**
* Runs a single iteration of the loop.
*
* This method should be called often in order to have a functioning
* Command system. The loop has five stages:
*
* <ol>
* <li>Poll the Buttons</li>
* <li>Execute/Remove the Commands</li>
* <li>Send values to SmartDashboard</li>
* <li>Add Commands</li>
* <li>Add Defaults</li>
* </ol>
*/
void Run();
/**
* Removes the Command from the Scheduler.
*
* @param command the command to remove
*/
void Remove(Command* command);
void RemoveAll();
/**
* Completely resets the scheduler. Undefined behavior if running.
*/
void ResetAll();
void SetEnabled(bool enabled);
void InitSendable(SendableBuilder& builder) override;
private:
Scheduler();
~Scheduler() override;
Scheduler(Scheduler&&) = default;
Scheduler& operator=(Scheduler&&) = default;
struct Impl;
std::unique_ptr<Impl> m_impl;
};
} // namespace frc

View File

@@ -1,29 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2011-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include "frc/commands/InstantCommand.h"
namespace frc {
class StartCommand : public InstantCommand {
public:
explicit StartCommand(Command* commandToStart);
virtual ~StartCommand() = default;
StartCommand(StartCommand&&) = default;
StartCommand& operator=(StartCommand&&) = default;
protected:
virtual void Initialize();
private:
Command* m_commandToFork;
};
} // namespace frc

View File

@@ -1,199 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2011-2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <memory>
#include <string>
#include <wpi/StringRef.h>
#include <wpi/Twine.h>
#include "frc/ErrorBase.h"
#include "frc/smartdashboard/Sendable.h"
#include "frc/smartdashboard/SendableHelper.h"
namespace frc {
class Command;
class Subsystem : public ErrorBase,
public Sendable,
public SendableHelper<Subsystem> {
friend class Scheduler;
public:
/**
* Creates a subsystem with the given name.
*
* @param name the name of the subsystem
*/
explicit Subsystem(const wpi::Twine& name);
Subsystem(Subsystem&&) = default;
Subsystem& operator=(Subsystem&&) = default;
/**
* Sets the default command. If this is not called or is called with null,
* then there will be no default command for the subsystem.
*
* <b>WARNING:</b> This should <b>NOT</b> be called in a constructor if the
* subsystem is a singleton.
*
* @param command the default command (or null if there should be none)
*/
void SetDefaultCommand(Command* command);
/**
* Returns the default command (or null if there is none).
*
* @return the default command
*/
Command* GetDefaultCommand();
/**
* Returns the default command name, or empty string is there is none.
*
* @return the default command name
*/
wpi::StringRef GetDefaultCommandName();
/**
* Sets the current command.
*
* @param command the new current command
*/
void SetCurrentCommand(Command* command);
/**
* Returns the command which currently claims this subsystem.
*
* @return the command which currently claims this subsystem
*/
Command* GetCurrentCommand() const;
/**
* Returns the current command name, or empty string if no current command.
*
* @return the current command name
*/
wpi::StringRef GetCurrentCommandName() const;
/**
* When the run method of the scheduler is called this method will be called.
*/
virtual void Periodic();
/**
* Initialize the default command for this subsystem.
*
* This is meant to be the place to call SetDefaultCommand in a subsystem and
* will be called on all the subsystems by the CommandBase method before the
* program starts running by using the list of all registered Subsystems
* inside the Scheduler.
*
* This should be overridden by a Subsystem that has a default Command
*/
virtual void InitDefaultCommand();
/**
* Gets the name of this Subsystem.
*
* @return Name
*/
std::string GetName() const;
/**
* Sets the name of this Subsystem.
*
* @param name name
*/
void SetName(const wpi::Twine& name);
/**
* Gets the subsystem name of this Subsystem.
*
* @return Subsystem name
*/
std::string GetSubsystem() const;
/**
* Sets the subsystem name of this Subsystem.
*
* @param subsystem subsystem name
*/
void SetSubsystem(const wpi::Twine& subsystem);
/**
* Associate a Sendable with this Subsystem.
* Also update the child's name.
*
* @param name name to give child
* @param child sendable
*/
void AddChild(const wpi::Twine& name, std::shared_ptr<Sendable> child);
/**
* Associate a Sendable with this Subsystem.
* Also update the child's name.
*
* @param name name to give child
* @param child sendable
*/
void AddChild(const wpi::Twine& name, Sendable* child);
/**
* Associate a Sendable with this Subsystem.
* Also update the child's name.
*
* @param name name to give child
* @param child sendable
*/
void AddChild(const wpi::Twine& name, Sendable& child);
/**
* Associate a {@link Sendable} with this Subsystem.
*
* @param child sendable
*/
void AddChild(std::shared_ptr<Sendable> child);
/**
* Associate a {@link Sendable} with this Subsystem.
*
* @param child sendable
*/
void AddChild(Sendable* child);
/**
* Associate a {@link Sendable} with this Subsystem.
*
* @param child sendable
*/
void AddChild(Sendable& child);
private:
/**
* Call this to alert Subsystem that the current command is actually the
* command.
*
* Sometimes, the Subsystem is told that it has no command while the Scheduler
* is going through the loop, only to be soon after given a new one. This will
* avoid that situation.
*/
void ConfirmCommand();
Command* m_currentCommand = nullptr;
bool m_currentCommandChanged = true;
Command* m_defaultCommand = nullptr;
bool m_initializedDefaultCommand = false;
public:
void InitSendable(SendableBuilder& builder) override;
};
} // namespace frc

View File

@@ -1,67 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <wpi/Twine.h>
#include "frc/commands/Command.h"
namespace frc {
/**
* A TimedCommand will wait for a timeout before finishing.
*
* TimedCommand is used to execute a command for a given amount of time.
*/
class TimedCommand : public Command {
public:
/**
* Creates a new TimedCommand with the given name and timeout.
*
* @param name the name of the command
* @param timeout the time (in seconds) before this command "times out"
*/
TimedCommand(const wpi::Twine& name, double timeout);
/**
* Creates a new WaitCommand with the given timeout.
*
* @param timeout the time (in seconds) before this command "times out"
*/
explicit TimedCommand(double timeout);
/**
* Creates a new TimedCommand with the given name and timeout.
*
* @param name the name of the command
* @param timeout the time (in seconds) before this command "times out"
* @param subsystem the subsystem that the command requires
*/
TimedCommand(const wpi::Twine& name, double timeout, Subsystem& subsystem);
/**
* Creates a new WaitCommand with the given timeout.
*
* @param timeout the time (in seconds) before this command "times out"
* @param subsystem the subsystem that the command requires
*/
TimedCommand(double timeout, Subsystem& subsystem);
virtual ~TimedCommand() = default;
TimedCommand(TimedCommand&&) = default;
TimedCommand& operator=(TimedCommand&&) = default;
protected:
/**
* Ends command when timed out.
*/
bool IsFinished() override;
};
} // namespace frc

View File

@@ -1,39 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2011-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <wpi/Twine.h>
#include "frc/commands/TimedCommand.h"
namespace frc {
class WaitCommand : public TimedCommand {
public:
/**
* Creates a new WaitCommand with the given name and timeout.
*
* @param name the name of the command
* @param timeout the time (in seconds) before this command "times out"
*/
explicit WaitCommand(double timeout);
/**
* Creates a new WaitCommand with the given timeout.
*
* @param timeout the time (in seconds) before this command "times out"
*/
WaitCommand(const wpi::Twine& name, double timeout);
virtual ~WaitCommand() = default;
WaitCommand(WaitCommand&&) = default;
WaitCommand& operator=(WaitCommand&&) = default;
};
} // namespace frc

View File

@@ -1,29 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2011-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <wpi/Twine.h>
#include "frc/commands/Command.h"
namespace frc {
class WaitForChildren : public Command {
public:
explicit WaitForChildren(double timeout);
WaitForChildren(const wpi::Twine& name, double timeout);
virtual ~WaitForChildren() = default;
WaitForChildren(WaitForChildren&&) = default;
WaitForChildren& operator=(WaitForChildren&&) = default;
protected:
virtual bool IsFinished();
};
} // namespace frc

View File

@@ -1,45 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2011-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <wpi/Twine.h>
#include "frc/commands/Command.h"
namespace frc {
class WaitUntilCommand : public Command {
public:
/**
* A WaitCommand will wait until a certain match time before finishing.
*
* This will wait until the game clock reaches some value, then continue to
* the next command.
*
* @see CommandGroup
*/
explicit WaitUntilCommand(double time);
WaitUntilCommand(const wpi::Twine& name, double time);
virtual ~WaitUntilCommand() = default;
WaitUntilCommand(WaitUntilCommand&&) = default;
WaitUntilCommand& operator=(WaitUntilCommand&&) = default;
protected:
/**
* Check if we've reached the actual finish time.
*/
virtual bool IsFinished();
private:
double m_time;
};
} // namespace frc

View File

@@ -1,242 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <frc/ErrorBase.h>
#include <frc/WPIErrors.h>
#include <frc2/command/Subsystem.h>
#include <memory>
#include <string>
#include <units/units.h>
#include <wpi/ArrayRef.h>
#include <wpi/Demangle.h>
#include <wpi/SmallSet.h>
#include <wpi/Twine.h>
namespace frc2 {
template <typename T>
std::string GetTypeName(const T& type) {
return wpi::Demangle(typeid(type).name());
}
class ParallelCommandGroup;
class ParallelRaceGroup;
class ParallelDeadlineGroup;
class SequentialCommandGroup;
class PerpetualCommand;
class ProxyScheduleCommand;
/**
* A state machine representing a complete action to be performed by the robot.
* Commands are run by the CommandScheduler, and can be composed into
* CommandGroups to allow users to build complicated multi-step actions without
* the need to roll the state machine logic themselves.
*
* <p>Commands are run synchronously from the main robot loop; no multithreading
* is used, unless specified explicitly from the command implementation.
*
* <p>Note: ALWAYS create a subclass by extending CommandHelper<Base, Subclass>,
* or decorators will not function!
*
* @see CommandScheduler
* @see CommandHelper
*/
class Command : public frc::ErrorBase {
public:
Command() = default;
virtual ~Command();
Command(const Command&);
Command& operator=(const Command&);
Command(Command&&) = default;
Command& operator=(Command&&) = default;
/**
* The initial subroutine of a command. Called once when the command is
* initially scheduled.
*/
virtual void Initialize();
/**
* The main body of a command. Called repeatedly while the command is
* scheduled.
*/
virtual void Execute();
/**
* The action to take when the command ends. Called when either the command
* finishes normally, or when it interrupted/canceled.
*
* @param interrupted whether the command was interrupted/canceled
*/
virtual void End(bool interrupted);
/**
* Whether the command has finished. Once a command finishes, the scheduler
* will call its end() method and un-schedule it.
*
* @return whether the command has finished.
*/
virtual bool IsFinished() { return false; }
/**
* Specifies the set of subsystems used by this command. Two commands cannot
* use the same subsystem at the same time. If the command is scheduled as
* interruptible and another command is scheduled that shares a requirement,
* the command will be interrupted. Else, the command will not be scheduled.
* If no subsystems are required, return an empty set.
*
* <p>Note: it is recommended that user implementations contain the
* requirements as a field, and return that field here, rather than allocating
* a new set every time this is called.
*
* @return the set of subsystems that are required
*/
virtual wpi::SmallSet<Subsystem*, 4> GetRequirements() const = 0;
/**
* Decorates this command with a timeout. If the specified timeout is
* exceeded before the command finishes normally, the command will be
* interrupted and un-scheduled. Note that the timeout only applies to the
* command returned by this method; the calling command is not itself changed.
*
* @param duration the timeout duration
* @return the command with the timeout added
*/
ParallelRaceGroup WithTimeout(units::second_t duration) &&;
/**
* Decorates this command with an interrupt condition. If the specified
* condition becomes true before the command finishes normally, the command
* will be interrupted and un-scheduled. Note that this only applies to the
* command returned by this method; the calling command is not itself changed.
*
* @param condition the interrupt condition
* @return the command with the interrupt condition added
*/
ParallelRaceGroup WithInterrupt(std::function<bool()> condition) &&;
/**
* Decorates this command with a runnable to run before this command starts.
*
* @param toRun the Runnable to run
* @return the decorated command
*/
SequentialCommandGroup BeforeStarting(std::function<void()> toRun) &&;
/**
* Decorates this command with a runnable to run after the command finishes.
*
* @param toRun the Runnable to run
* @return the decorated command
*/
SequentialCommandGroup AndThen(std::function<void()> toRun) &&;
/**
* Decorates this command to run perpetually, ignoring its ordinary end
* conditions. The decorated command can still be interrupted or canceled.
*
* @return the decorated command
*/
PerpetualCommand Perpetually() &&;
/**
* 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 command's requirements to the
* entire command group.
*
* @return the decorated command
*/
ProxyScheduleCommand AsProxy();
/**
* Schedules this command.
*
* @param interruptible whether this command can be interrupted by another
* command that shares one of its requirements
*/
void Schedule(bool interruptible);
/**
* Schedules this command, defaulting to interruptible.
*/
void Schedule() { Schedule(true); }
/**
* Cancels this command. Will call the command's interrupted() method.
* Commands will be canceled even if they are not marked as interruptible.
*/
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.
*
* @return Whether the command is scheduled.
*/
bool IsScheduled() const;
/**
* Whether the command requires a given subsystem. Named "hasRequirement"
* rather than "requires" to avoid confusion with
* {@link
* edu.wpi.first.wpilibj.command.Command#requires(edu.wpi.first.wpilibj.command.Subsystem)}
* - this may be able to be changed in a few years.
*
* @param requirement the subsystem to inquire about
* @return whether the subsystem is required
*/
bool HasRequirement(Subsystem* requirement) const;
/**
* Whether the command is currently grouped in a command group. Used as extra
* insurance to prevent accidental independent use of grouped commands.
*/
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!
*/
void SetGrouped(bool grouped);
/**
* Whether the given command should run when the robot is disabled. Override
* to return true if the command should run when disabled.
*
* @return whether the command should run when the robot is disabled
*/
virtual bool RunsWhenDisabled() const { return false; }
virtual std::string GetName() const;
protected:
/**
* Transfers ownership of this command to a unique pointer. Used for
* decorator methods.
*/
virtual std::unique_ptr<Command> TransferOwnership() && = 0;
bool m_isGrouped = false;
};
/**
* Checks if two commands have disjoint requirement sets.
*
* @param first The first command to check.
* @param second The second command to check.
* @return False if first and second share a requirement.
*/
bool RequirementsDisjoint(Command* first, Command* second);
} // namespace frc2

View File

@@ -1,73 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <frc/smartdashboard/Sendable.h>
#include <frc/smartdashboard/SendableHelper.h>
#include <string>
#include <wpi/SmallSet.h>
#include <wpi/Twine.h>
#include "Command.h"
namespace frc2 {
/**
* A Sendable base class for Commands.
*/
class CommandBase : public Command,
public frc::Sendable,
public frc::SendableHelper<CommandBase> {
public:
/**
* Adds the specified requirements to the command.
*
* @param requirements the requirements to add
*/
void AddRequirements(std::initializer_list<Subsystem*> requirements);
void AddRequirements(wpi::SmallSet<Subsystem*, 4> requirements);
wpi::SmallSet<Subsystem*, 4> GetRequirements() const override;
/**
* Sets the name of this Command.
*
* @param name name
*/
void SetName(const wpi::Twine& name);
/**
* Gets the name of this Command.
*
* @return Name
*/
std::string GetName() const override;
/**
* Gets the subsystem name of this Command.
*
* @return Subsystem name
*/
std::string GetSubsystem() const;
/**
* Sets the subsystem name of this Command.
*
* @param subsystem subsystem name
*/
void SetSubsystem(const wpi::Twine& subsystem);
void InitSendable(frc::SendableBuilder& builder) override;
protected:
CommandBase();
wpi::SmallSet<Subsystem*, 4> m_requirements;
};
} // namespace frc2

View File

@@ -1,62 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <frc/ErrorBase.h>
#include <memory>
#include <set>
#include <vector>
#include "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.
*/
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 commands The command to check
* @return True if all the command is ungrouped.
*/
static bool RequireUngrouped(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(wpi::ArrayRef<std::unique_ptr<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::initializer_list<Command*>);
/**
* Adds the given commands to the command group.
*
* @param commands The commands to add.
*/
virtual void AddCommands(
std::vector<std::unique_ptr<Command>>&& commands) = 0;
};
} // namespace frc2

View File

@@ -1,37 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <memory>
#include <type_traits>
#include <utility>
#include "Command.h"
namespace frc2 {
/**
* CRTP implementation to allow polymorphic decorator functions in Command.
*
* <p>Note: ALWAYS create a subclass by extending CommandHelper<Base, Subclass>,
* or decorators will not function!
*/
template <typename Base, typename CRTP,
typename = std::enable_if_t<std::is_base_of_v<Command, Base>>>
class CommandHelper : public Base {
using Base::Base;
public:
CommandHelper() = default;
protected:
std::unique_ptr<Command> TransferOwnership() && override {
return std::make_unique<CRTP>(std::move(*static_cast<CRTP*>(this)));
}
};
} // namespace frc2

View File

@@ -1,372 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <frc/ErrorBase.h>
#include <frc/RobotState.h>
#include <frc/WPIErrors.h>
#include <frc/smartdashboard/Sendable.h>
#include <frc/smartdashboard/SendableHelper.h>
#include <memory>
#include <unordered_map>
#include <utility>
#include <networktables/NetworkTableEntry.h>
#include <wpi/DenseMap.h>
#include <wpi/FunctionExtras.h>
#include <wpi/SmallSet.h>
#include "CommandState.h"
namespace frc2 {
class Command;
class Subsystem;
/**
* The scheduler responsible for running Commands. A Command-based robot should
* call Run() on the singleton instance in its periodic block in order to run
* commands synchronously from the main loop. Subsystems should be registered
* with the scheduler using RegisterSubsystem() in order for their Periodic()
* methods to be called and for their default commands to be scheduled.
*/
class CommandScheduler final : public frc::Sendable,
public frc::ErrorBase,
public frc::SendableHelper<CommandScheduler> {
public:
/**
* Returns the Scheduler instance.
*
* @return the instance
*/
static CommandScheduler& GetInstance();
using Action = std::function<void(const Command&)>;
/**
* Adds a button binding to the scheduler, which will be polled to schedule
* commands.
*
* @param button The button to add
*/
void AddButton(wpi::unique_function<void()> button);
/**
* Removes all button bindings from the scheduler.
*/
void ClearButtons();
/**
* Schedules a command for execution. Does nothing if the command is already
* scheduled. If a command's requirements are not available, it will only be
* started if all the commands currently using those requirements have been
* scheduled as interruptible. If this is the case, they will be interrupted
* and the command will be scheduled.
*
* @param interruptible whether this command can be interrupted
* @param command the command to schedule
*/
void Schedule(bool interruptible, Command* command);
/**
* Schedules a command for execution, with interruptible defaulted to true.
* Does nothing if the command is already scheduled.
*
* @param command the command to schedule
*/
void Schedule(Command* command);
/**
* Schedules multiple commands for execution. Does nothing if the command is
* already scheduled. If a command's requirements are not available, it will
* only be started if all the commands currently using those requirements have
* been scheduled as interruptible. If this is the case, they will be
* interrupted and the command will be scheduled.
*
* @param interruptible whether the commands should be interruptible
* @param commands the commands to schedule
*/
void Schedule(bool interruptible, wpi::ArrayRef<Command*> commands);
/**
* Schedules multiple commands for execution. Does nothing if the command is
* already scheduled. If a command's requirements are not available, it will
* only be started if all the commands currently using those requirements have
* been scheduled as interruptible. If this is the case, they will be
* interrupted and the command will be scheduled.
*
* @param interruptible whether the commands should be interruptible
* @param commands the commands to schedule
*/
void Schedule(bool interruptible, std::initializer_list<Command*> commands);
/**
* Schedules multiple commands for execution, with interruptible defaulted to
* true. Does nothing if the command is already scheduled.
*
* @param commands the commands to schedule
*/
void Schedule(wpi::ArrayRef<Command*> commands);
/**
* Schedules multiple commands for execution, with interruptible defaulted to
* true. Does nothing if the command is already scheduled.
*
* @param commands the commands to schedule
*/
void Schedule(std::initializer_list<Command*> commands);
/**
* Runs a single iteration of the scheduler. The execution occurs in the
* following order:
*
* <p>Subsystem periodic methods are called.
*
* <p>Button bindings are polled, and new commands are scheduled from them.
*
* <p>Currently-scheduled commands are executed.
*
* <p>End conditions are checked on currently-scheduled commands, and commands
* that are finished have their end methods called and are removed.
*
* <p>Any subsystems not being used as requirements have their default methods
* started.
*/
void Run();
/**
* Registers subsystems with the scheduler. This must be called for the
* subsystem's periodic block to run when the scheduler is run, and for the
* subsystem's default command to be scheduled. It is recommended to call
* this from the constructor of your subsystem implementations.
*
* @param subsystem the subsystem to register
*/
void RegisterSubsystem(Subsystem* subsystem);
/**
* Un-registers subsystems with the scheduler. The subsystem will no longer
* have its periodic block called, and will not have its default command
* scheduled.
*
* @param subsystem the subsystem to un-register
*/
void UnregisterSubsystem(Subsystem* subsystem);
void RegisterSubsystem(std::initializer_list<Subsystem*> subsystems);
void UnregisterSubsystem(std::initializer_list<Subsystem*> subsystems);
/**
* Sets the default command for a subsystem. Registers that subsystem if it
* is not already registered. Default commands will run whenever there is no
* other command currently scheduled that requires the subsystem. Default
* commands should be written to never end (i.e. their IsFinished() method
* should return false), as they would simply be re-scheduled if they do.
* Default commands must also require their subsystem.
*
* @param subsystem the subsystem whose default command will be set
* @param defaultCommand the default command to associate with the subsystem
*/
template <class T, typename = std::enable_if_t<std::is_base_of_v<
Command, std::remove_reference_t<T>>>>
void SetDefaultCommand(Subsystem* subsystem, T&& defaultCommand) {
if (!defaultCommand.HasRequirement(subsystem)) {
wpi_setWPIErrorWithContext(
CommandIllegalUse, "Default commands must require their subsystem!");
return;
}
if (defaultCommand.IsFinished()) {
wpi_setWPIErrorWithContext(CommandIllegalUse,
"Default commands should not end!");
return;
}
m_subsystems[subsystem] = std::make_unique<std::remove_reference_t<T>>(
std::forward<T>(defaultCommand));
}
/**
* Gets the default command associated with this subsystem. Null if this
* subsystem has no default command associated with it.
*
* @param subsystem the subsystem to inquire about
* @return the default command associated with the subsystem
*/
Command* GetDefaultCommand(const Subsystem* subsystem) const;
/**
* Cancels a command. The scheduler will only call the interrupted method of
* a canceled command, not the end method (though the interrupted method may
* itself call the end method). Commands will be canceled even if they are
* not scheduled as interruptible.
*
* @param command the command to cancel
*/
void Cancel(Command* command);
/**
* Cancels commands. The scheduler will only call the interrupted method of a
* canceled command, not the end method (though the interrupted method may
* itself call the end method). Commands will be canceled even if they are
* not scheduled as interruptible.
*
* @param commands the commands to cancel
*/
void Cancel(wpi::ArrayRef<Command*> commands);
/**
* Cancels commands. The scheduler will only call the interrupted method of a
* canceled command, not the end method (though the interrupted method may
* itself call the end method). Commands will be canceled even if they are
* not scheduled as interruptible.
*
* @param commands the commands to cancel
*/
void Cancel(std::initializer_list<Command*> commands);
/**
* Cancels all commands that are currently scheduled.
*/
void CancelAll();
/**
* Returns the time since a given command was scheduled. Note that this only
* works on commands that are directly scheduled by the scheduler; it will not
* work on commands inside of commandgroups, as the scheduler does not see
* them.
*
* @param command the command to query
* @return the time since the command was scheduled, in seconds
*/
double TimeSinceScheduled(const Command* command) const;
/**
* Whether the given commands are running. Note that this only works on
* commands that are directly scheduled by the scheduler; it will not work on
* commands inside of CommandGroups, as the scheduler does not see them.
*
* @param commands the command to query
* @return whether the command is currently scheduled
*/
bool IsScheduled(wpi::ArrayRef<const Command*> commands) const;
/**
* Whether the given commands are running. Note that this only works on
* commands that are directly scheduled by the scheduler; it will not work on
* commands inside of CommandGroups, as the scheduler does not see them.
*
* @param commands the command to query
* @return whether the command is currently scheduled
*/
bool IsScheduled(std::initializer_list<const Command*> commands) const;
/**
* Whether a given command is running. Note that this only works on commands
* that are directly scheduled by the scheduler; it will not work on commands
* inside of CommandGroups, as the scheduler does not see them.
*
* @param commands the command to query
* @return whether the command is currently scheduled
*/
bool IsScheduled(const Command* command) const;
/**
* Returns the command currently requiring a given subsystem. Null if no
* command is currently requiring the subsystem
*
* @param subsystem the subsystem to be inquired about
* @return the command currently requiring the subsystem
*/
Command* Requiring(const Subsystem* subsystem) const;
/**
* Disables the command scheduler.
*/
void Disable();
/**
* Enables the command scheduler.
*/
void Enable();
/**
* Adds an action to perform on the initialization of any command by the
* scheduler.
*
* @param action the action to perform
*/
void OnCommandInitialize(Action action);
/**
* Adds an action to perform on the execution of any command by the scheduler.
*
* @param action the action to perform
*/
void OnCommandExecute(Action action);
/**
* Adds an action to perform on the interruption of any command by the
* scheduler.
*
* @param action the action to perform
*/
void OnCommandInterrupt(Action action);
/**
* Adds an action to perform on the finishing of any command by the scheduler.
*
* @param action the action to perform
*/
void OnCommandFinish(Action action);
void InitSendable(frc::SendableBuilder& builder) override;
private:
// Constructor; private as this is a singleton
CommandScheduler();
// A map from commands to their scheduling state. Also used as a set of the
// currently-running commands.
wpi::DenseMap<Command*, CommandState> m_scheduledCommands;
// A map from required subsystems to their requiring commands. Also used as a
// set of the currently-required subsystems.
wpi::DenseMap<Subsystem*, Command*> m_requirements;
// A map from subsystems registered with the scheduler to their default
// commands. Also used as a list of currently-registered subsystems.
wpi::DenseMap<Subsystem*, std::unique_ptr<Command>> m_subsystems;
// The set of currently-registered buttons that will be polled every
// iteration.
wpi::SmallVector<wpi::unique_function<void()>, 4> m_buttons;
bool m_disabled{false};
// NetworkTable entries for use in Sendable impl
nt::NetworkTableEntry m_namesEntry;
nt::NetworkTableEntry m_idsEntry;
nt::NetworkTableEntry m_cancelEntry;
// Lists of user-supplied actions to be executed on scheduling events for
// every command.
wpi::SmallVector<Action, 4> m_initActions;
wpi::SmallVector<Action, 4> m_executeActions;
wpi::SmallVector<Action, 4> m_interruptActions;
wpi::SmallVector<Action, 4> m_finishActions;
// Flag and queues for avoiding concurrent modification if commands are
// scheduled/canceled during run
bool m_inRunLoop = false;
wpi::DenseMap<Command*, bool> m_toSchedule;
wpi::SmallVector<Command*, 4> m_toCancel;
friend class CommandTestBase;
};
} // namespace frc2

View File

@@ -1,33 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
namespace frc2 {
/**
* Class that holds scheduling state for a command. Used internally by the
* CommandScheduler
*/
class CommandState final {
public:
CommandState() = default;
explicit CommandState(bool interruptible);
bool IsInterruptible() const { return m_interruptible; }
// The time since this command was initialized.
double TimeSinceInitialized() const;
private:
double m_startTime = -1;
bool m_interruptible;
void StartTiming();
void StartRunning();
};
} // namespace frc2

View File

@@ -1,92 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <iostream>
#include <memory>
#include <utility>
#include "CommandBase.h"
#include "CommandGroupBase.h"
#include "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.
*
* <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.
*
* @see ScheduleCommand
*/
class ConditionalCommand
: public CommandHelper<CommandBase, ConditionalCommand> {
public:
/**
* Creates a new ConditionalCommand.
*
* @param onTrue the command to run if the condition is true
* @param onFalse the command to run if the condition is false
* @param condition the condition to determine which command to run
*/
template <class T1, class T2,
typename = std::enable_if_t<
std::is_base_of_v<Command, std::remove_reference_t<T1>>>,
typename = std::enable_if_t<
std::is_base_of_v<Command, std::remove_reference_t<T2>>>>
ConditionalCommand(T1&& onTrue, T2&& onFalse, std::function<bool()> condition)
: ConditionalCommand(std::make_unique<std::remove_reference_t<T1>>(
std::forward<T1>(onTrue)),
std::make_unique<std::remove_reference_t<T2>>(
std::forward<T2>(onFalse)),
condition) {}
/**
* Creates a new ConditionalCommand.
*
* @param onTrue the command to run if the condition is true
* @param onFalse the command to run if the condition is false
* @param condition the condition to determine which command to run
*/
ConditionalCommand(std::unique_ptr<Command>&& onTrue,
std::unique_ptr<Command>&& onFalse,
std::function<bool()> condition);
ConditionalCommand(ConditionalCommand&& other) = default;
// No copy constructors for command groups
ConditionalCommand(const ConditionalCommand& other) = delete;
void Initialize() override;
void Execute() override;
void End(bool interrupted) override;
bool IsFinished() override;
bool RunsWhenDisabled() const override;
private:
std::unique_ptr<Command> m_onTrue;
std::unique_ptr<Command> m_onFalse;
std::function<bool()> m_condition;
Command* m_selectedCommand{nullptr};
bool m_runsWhenDisabled = true;
};
} // namespace frc2

View File

@@ -1,56 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include "CommandBase.h"
#include "CommandHelper.h"
namespace frc2 {
/**
* A command that allows the user to pass in functions for each of the basic
* command methods through the constructor. Useful for inline definitions of
* complex commands - note, however, that if a command is beyond a certain
* complexity it is usually better practice to write a proper class for it than
* to inline it.
*/
class FunctionalCommand : public CommandHelper<CommandBase, FunctionalCommand> {
public:
/**
* Creates a new FunctionalCommand.
*
* @param onInit the function to run on command initialization
* @param onExecute the function to run on command execution
* @param onEnd the function to run on command end
* @param isFinished the function that determines whether the command has
* finished
* @param requirements the subsystems required by this command
*/
FunctionalCommand(std::function<void()> onInit,
std::function<void()> onExecute,
std::function<void(bool)> onEnd,
std::function<bool()> isFinished);
FunctionalCommand(FunctionalCommand&& other) = default;
FunctionalCommand(const FunctionalCommand& other) = default;
void Initialize() override;
void Execute() override;
void End(bool interrupted) override;
bool IsFinished() override;
private:
std::function<void()> m_onInit;
std::function<void()> m_onExecute;
std::function<void(bool)> m_onEnd;
std::function<bool()> m_isFinished;
};
} // namespace frc2

View File

@@ -1,48 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include "CommandBase.h"
#include "CommandHelper.h"
namespace frc2 {
/**
* A Command that runs instantly; it will initialize, execute once, and end on
* the same iteration of the scheduler. Users can either pass in a Runnable and
* a set of requirements, or else subclass this command if desired.
*/
class InstantCommand : public CommandHelper<CommandBase, InstantCommand> {
public:
/**
* Creates a new InstantCommand that runs the given Runnable with the given
* requirements.
*
* @param toRun the Runnable to run
* @param requirements the subsystems required by this command
*/
InstantCommand(std::function<void()> toRun,
std::initializer_list<Subsystem*> requirements);
InstantCommand(InstantCommand&& other) = default;
InstantCommand(const InstantCommand& other) = default;
/**
* Creates a new InstantCommand with a Runnable that does nothing. Useful
* only as a no-arg constructor to call implicitly from subclass constructors.
*/
InstantCommand();
void Initialize() override;
bool IsFinished() final;
private:
std::function<void()> m_toRun;
};
} // namespace frc2

View File

@@ -1,53 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <frc/Notifier.h>
#include <units/units.h>
#include "CommandBase.h"
#include "CommandHelper.h"
namespace frc2 {
/**
* A command that starts a notifier to run the given runnable periodically in a
* separate thread. Has no end condition as-is; either subclass it or use {@link
* Command#withTimeout(double)} or
* {@link Command#withInterrupt(BooleanSupplier)} to give it one.
*
* <p>WARNING: Do not use this class unless you are confident in your ability to
* make the executed code thread-safe. If you do not know what "thread-safe"
* means, that is a good sign that you should not use this class.
*/
class NotifierCommand : public CommandHelper<CommandBase, NotifierCommand> {
public:
/**
* Creates a new NotifierCommand.
*
* @param toRun the runnable for the notifier to run
* @param period the period at which the notifier should run
* @param requirements the subsystems required by this command
*/
NotifierCommand(std::function<void()> toRun, units::second_t period,
std::initializer_list<Subsystem*> requirements);
NotifierCommand(NotifierCommand&& other);
NotifierCommand(const NotifierCommand& other);
void Initialize() override;
void End(bool interrupted) override;
private:
std::function<void()> m_toRun;
frc::Notifier m_notifier;
units::second_t m_period;
};
} // namespace frc2

View File

@@ -1,79 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include "frc/controller/PIDController.h"
#include "frc2/command/CommandBase.h"
#include "frc2/command/CommandHelper.h"
namespace frc2 {
/**
* A command that controls an output with a PIDController. Runs forever by
* default - to add exit conditions and/or other behavior, subclass this class.
* The controller calculation and output are performed synchronously in the
* command's execute() method.
*
* @see PIDController
*/
class PIDCommand : public CommandHelper<CommandBase, PIDCommand> {
public:
/**
* Creates a new PIDCommand, which controls the given output with a
* PIDController.
*
* @param controller the controller that controls the output.
* @param measurementSource the measurement of the process variable
* @param setpointSource the controller's reference (aka setpoint)
* @param useOutput the controller's output
* @param requirements the subsystems required by this command
*/
PIDCommand(PIDController controller,
std::function<double()> measurementSource,
std::function<double()> setpointSource,
std::function<void(double)> useOutput,
std::initializer_list<Subsystem*> requirements);
/**
* Creates a new PIDCommand, which controls the given output with a
* PIDController with a constant setpoint.
*
* @param controller the controller that controls the output.
* @param measurementSource the measurement of the process variable
* @param setpoint the controller's setpoint (aka setpoint)
* @param useOutput the controller's output
* @param requirements the subsystems required by this command
*/
PIDCommand(PIDController controller,
std::function<double()> measurementSource, double setpoint,
std::function<void(double)> useOutput,
std::initializer_list<Subsystem*> requirements);
PIDCommand(PIDCommand&& other) = default;
PIDCommand(const PIDCommand& other) = default;
void Initialize() override;
void Execute() override;
void End(bool interrupted) override;
/**
* Returns the PIDController used by the command.
*
* @return The PIDController
*/
PIDController& getController();
protected:
PIDController m_controller;
std::function<double()> m_measurement;
std::function<double()> m_setpoint;
std::function<void(double)> m_useOutput;
};
} // namespace frc2

View File

@@ -1,73 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include "frc/controller/PIDController.h"
#include "frc2/command/SubsystemBase.h"
namespace frc2 {
/**
* A subsystem that uses a PIDController to control an output. The controller
* is run synchronously from the subsystem's periodic() method.
*
* @see PIDController
*/
class PIDSubsystem : public SubsystemBase {
public:
/**
* Creates a new PIDSubsystem.
*
* @param controller the PIDController to use
*/
explicit PIDSubsystem(PIDController controller);
void Periodic() override;
/**
* Uses the output from the PIDController.
*
* @param output the output of the PIDController
*/
virtual void UseOutput(double output) = 0;
/**
* Returns the reference (setpoint) used by the PIDController.
*
* @return the reference (setpoint) to be used by the controller
*/
virtual double GetSetpoint() = 0;
/**
* Returns the measurement of the process variable used by the PIDController.
*
* @return the measurement of the process variable
*/
virtual double GetMeasurement() = 0;
/**
* Enables the PID control. Resets the controller.
*/
virtual void Enable();
/**
* Disables the PID control. Sets output to zero.
*/
virtual void Disable();
/**
* Returns the PIDController.
*
* @return The controller.
*/
PIDController& GetController();
protected:
PIDController m_controller;
bool m_enabled;
};
} // namespace frc2

View File

@@ -1,100 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#ifdef _WIN32
#pragma warning(push)
#pragma warning(disable : 4521)
#endif
#include <memory>
#include <unordered_map>
#include <utility>
#include <vector>
#include "CommandGroupBase.h"
#include "CommandHelper.h"
namespace frc2 {
/**
* A CommandGroup 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.
*/
class ParallelCommandGroup
: public CommandHelper<CommandGroupBase, ParallelCommandGroup> {
public:
/**
* 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
* still running will be interrupted.
*
* @param commands the commands to include in this group.
*/
explicit ParallelCommandGroup(
std::vector<std::unique_ptr<Command>>&& commands);
/**
* 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
* still running will be interrupted.
*
* @param commands the commands to include in this group.
*/
template <class... Types,
typename = std::enable_if_t<std::conjunction_v<
std::is_base_of<Command, std::remove_reference_t<Types>>...>>>
explicit ParallelCommandGroup(Types&&... commands) {
AddCommands(std::forward<Types>(commands)...);
}
ParallelCommandGroup(ParallelCommandGroup&& other) = default;
// No copy constructors for commandgroups
ParallelCommandGroup(const ParallelCommandGroup&) = delete;
// Prevent template expansion from emulating copy ctor
ParallelCommandGroup(ParallelCommandGroup&) = delete;
template <class... Types,
typename = std::enable_if_t<std::conjunction_v<
std::is_base_of<Command, std::remove_reference_t<Types>>...>>>
void AddCommands(Types&&... commands) {
std::vector<std::unique_ptr<Command>> foo;
((void)foo.emplace_back(std::make_unique<std::remove_reference_t<Types>>(
std::forward<Types>(commands))),
...);
AddCommands(std::move(foo));
}
void Initialize() override;
void Execute() override;
void End(bool interrupted) override;
bool IsFinished() override;
bool RunsWhenDisabled() const override;
private:
void AddCommands(std::vector<std::unique_ptr<Command>>&& commands) override;
std::unordered_map<std::unique_ptr<Command>, bool> m_commands;
bool m_runWhenDisabled{true};
bool isRunning = false;
};
} // namespace frc2
#ifdef _WIN32
#pragma warning(pop)
#endif

View File

@@ -1,111 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#ifdef _WIN32
#pragma warning(push)
#pragma warning(disable : 4521)
#endif
#include <memory>
#include <unordered_map>
#include <utility>
#include <vector>
#include "CommandGroupBase.h"
#include "CommandHelper.h"
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.
*
* <p>As a rule, CommandGroups require the union of the requirements of their
* component commands.
*/
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
* interrupted.
*
* @param deadline the command that determines when the group 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
* interrupted.
*
* @param deadline the command that determines when the group ends
* @param commands the commands to be executed
*/
template <class T, class... Types,
typename = std::enable_if_t<
std::is_base_of_v<Command, std::remove_reference_t<T>>>,
typename = std::enable_if_t<std::conjunction_v<
std::is_base_of<Command, std::remove_reference_t<Types>>...>>>
explicit ParallelDeadlineGroup(T&& deadline, Types&&... commands) {
SetDeadline(std::make_unique<std::remove_reference_t<T>>(
std::forward<T>(deadline)));
AddCommands(std::forward<Types>(commands)...);
}
ParallelDeadlineGroup(ParallelDeadlineGroup&& other) = default;
// No copy constructors for command groups
ParallelDeadlineGroup(const ParallelDeadlineGroup&) = delete;
// Prevent template expansion from emulating copy ctor
ParallelDeadlineGroup(ParallelDeadlineGroup&) = delete;
template <class... Types,
typename = std::enable_if_t<std::conjunction_v<
std::is_base_of<Command, std::remove_reference_t<Types>>...>>>
void AddCommands(Types&&... commands) {
std::vector<std::unique_ptr<Command>> foo;
((void)foo.emplace_back(std::make_unique<std::remove_reference_t<Types>>(
std::forward<Types>(commands))),
...);
AddCommands(std::move(foo));
}
void Initialize() override;
void Execute() override;
void End(bool interrupted) override;
bool IsFinished() override;
bool RunsWhenDisabled() const override;
private:
void AddCommands(std::vector<std::unique_ptr<Command>>&& commands) override;
void SetDeadline(std::unique_ptr<Command>&& deadline);
std::unordered_map<std::unique_ptr<Command>, bool> m_commands;
Command* m_deadline;
bool m_runWhenDisabled{true};
bool isRunning = false;
};
} // namespace frc2
#ifdef _WIN32
#pragma warning(pop)
#endif

View File

@@ -1,90 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#ifdef _WIN32
#pragma warning(push)
#pragma warning(disable : 4521)
#endif
#include <memory>
#include <set>
#include <unordered_map>
#include <utility>
#include <vector>
#include "CommandGroupBase.h"
#include "CommandHelper.h"
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.
*
* <p>As a rule, CommandGroups require the union of the requirements of their
* component commands.
*/
class ParallelRaceGroup
: public CommandHelper<CommandGroupBase, ParallelRaceGroup> {
public:
/**
* 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.
*/
explicit ParallelRaceGroup(std::vector<std::unique_ptr<Command>>&& commands);
template <class... Types,
typename = std::enable_if_t<std::conjunction_v<
std::is_base_of<Command, std::remove_reference_t<Types>>...>>>
explicit ParallelRaceGroup(Types&&... commands) {
AddCommands(std::forward<Types>(commands)...);
}
ParallelRaceGroup(ParallelRaceGroup&& other) = default;
// No copy constructors for command groups
ParallelRaceGroup(const ParallelRaceGroup&) = delete;
// Prevent template expansion from emulating copy ctor
ParallelRaceGroup(ParallelRaceGroup&) = delete;
template <class... Types>
void AddCommands(Types&&... commands) {
std::vector<std::unique_ptr<Command>> foo;
((void)foo.emplace_back(std::make_unique<std::remove_reference_t<Types>>(
std::forward<Types>(commands))),
...);
AddCommands(std::move(foo));
}
void Initialize() override;
void Execute() override;
void End(bool interrupted) override;
bool IsFinished() override;
bool RunsWhenDisabled() const override;
private:
void AddCommands(std::vector<std::unique_ptr<Command>>&& commands) override;
std::set<std::unique_ptr<Command>> m_commands;
bool m_runWhenDisabled{true};
bool m_finished{false};
bool isRunning = false;
};
} // namespace frc2
#ifdef _WIN32
#pragma warning(pop)
#endif

View File

@@ -1,78 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#ifdef _WIN32
#pragma warning(push)
#pragma warning(disable : 4521)
#endif
#include <memory>
#include <utility>
#include "CommandBase.h"
#include "CommandGroupBase.h"
#include "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},
* 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.
*
* <p>As a rule, CommandGroups require the union of the requirements of their
* component commands.
*/
class PerpetualCommand : public CommandHelper<CommandBase, PerpetualCommand> {
public:
/**
* Creates a new PerpetualCommand. Will run another command in perpetuity,
* ignoring that command's end conditions, unless this command itself is
* interrupted.
*
* @param command the command to run perpetually
*/
explicit PerpetualCommand(std::unique_ptr<Command>&& command);
/**
* Creates a new PerpetualCommand. Will run another command in perpetuity,
* ignoring that command's end conditions, unless this command itself is
* interrupted.
*
* @param command the command to run perpetually
*/
template <class T, typename = std::enable_if_t<std::is_base_of_v<
Command, std::remove_reference_t<T>>>>
explicit PerpetualCommand(T&& command)
: PerpetualCommand(std::make_unique<std::remove_reference_t<T>>(
std::forward<T>(command))) {}
PerpetualCommand(PerpetualCommand&& other) = default;
// No copy constructors for command groups
PerpetualCommand(const PerpetualCommand& other) = delete;
// Prevent template expansion from emulating copy ctor
PerpetualCommand(PerpetualCommand&) = delete;
void Initialize() override;
void Execute() override;
void End(bool interrupted) override;
private:
std::unique_ptr<Command> m_command;
};
} // namespace frc2
#ifdef _WIN32
#pragma warning(pop)
#endif

View File

@@ -1,35 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <wpi/Twine.h>
#include <wpi/raw_ostream.h>
#include "CommandHelper.h"
#include "InstantCommand.h"
namespace frc2 {
/**
* A command that prints a string when initialized.
*/
class PrintCommand : public CommandHelper<InstantCommand, PrintCommand> {
public:
/**
* Creates a new a PrintCommand.
*
* @param message the message to print
*/
explicit PrintCommand(const wpi::Twine& message);
PrintCommand(PrintCommand&& other) = default;
PrintCommand(const PrintCommand& other) = default;
bool RunsWhenDisabled() const override;
};
} // namespace frc2

View File

@@ -1,116 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <units/units.h>
#include "frc/controller/ProfiledPIDController.h"
#include "frc2/command/CommandBase.h"
#include "frc2/command/CommandHelper.h"
namespace frc2 {
/**
* A command that controls an output with a ProfiledPIDController. Runs forever
* by default - to add exit conditions and/or other behavior, subclass this
* class. The controller calculation and output are performed synchronously in
* the command's execute() method.
*
* @see ProfiledPIDController
*/
class ProfiledPIDCommand
: public CommandHelper<CommandBase, ProfiledPIDCommand> {
using State = frc::TrapezoidProfile::State;
public:
/**
* Creates a new PIDCommand, which controls the given output with a
* ProfiledPIDController.
*
* @param controller the controller that controls the output.
* @param measurementSource the measurement of the process variable
* @param goalSource the controller's goal
* @param useOutput the controller's output
* @param requirements the subsystems required by this command
*/
ProfiledPIDCommand(frc::ProfiledPIDController controller,
std::function<units::meter_t()> measurementSource,
std::function<State()> goalSource,
std::function<void(double, State)> useOutput,
std::initializer_list<Subsystem*> requirements);
/**
* Creates a new PIDCommand, which controls the given output with a
* ProfiledPIDController.
*
* @param controller the controller that controls the output.
* @param measurementSource the measurement of the process variable
* @param goalSource the controller's goal
* @param useOutput the controller's output
* @param requirements the subsystems required by this command
*/
ProfiledPIDCommand(frc::ProfiledPIDController controller,
std::function<units::meter_t()> measurementSource,
std::function<units::meter_t()> goalSource,
std::function<void(double, State)> useOutput,
std::initializer_list<Subsystem*> requirements);
/**
* Creates a new PIDCommand, which controls the given output with a
* ProfiledPIDController with a constant goal.
*
* @param controller the controller that controls the output.
* @param measurementSource the measurement of the process variable
* @param goal the controller's goal
* @param useOutput the controller's output
* @param requirements the subsystems required by this command
*/
ProfiledPIDCommand(frc::ProfiledPIDController controller,
std::function<units::meter_t()> measurementSource,
State goal, std::function<void(double, State)> useOutput,
std::initializer_list<Subsystem*> requirements);
/**
* Creates a new PIDCommand, which controls the given output with a
* ProfiledPIDController with a constant goal.
*
* @param controller the controller that controls the output.
* @param measurementSource the measurement of the process variable
* @param goal the controller's goal
* @param useOutput the controller's output
* @param requirements the subsystems required by this command
*/
ProfiledPIDCommand(frc::ProfiledPIDController controller,
std::function<units::meter_t()> measurementSource,
units::meter_t goal,
std::function<void(double, State)> useOutput,
std::initializer_list<Subsystem*> requirements);
ProfiledPIDCommand(ProfiledPIDCommand&& other) = default;
ProfiledPIDCommand(const ProfiledPIDCommand& other) = default;
void Initialize() override;
void Execute() override;
void End(bool interrupted) override;
/**
* Returns the ProfiledPIDController used by the command.
*
* @return The ProfiledPIDController
*/
frc::ProfiledPIDController& GetController();
protected:
frc::ProfiledPIDController m_controller;
std::function<units::meter_t()> m_measurement;
std::function<State()> m_goal;
std::function<void(double, State)> m_useOutput;
};
} // namespace frc2

View File

@@ -1,78 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <units/units.h>
#include "frc/controller/ProfiledPIDController.h"
#include "frc2/command/SubsystemBase.h"
namespace frc2 {
/**
* A subsystem that uses a ProfiledPIDController to control an output. The
* controller is run synchronously from the subsystem's periodic() method.
*
* @see ProfiledPIDController
*/
class ProfiledPIDSubsystem : public SubsystemBase {
using State = frc::TrapezoidProfile::State;
public:
/**
* Creates a new ProfiledPIDSubsystem.
*
* @param controller the ProfiledPIDController to use
*/
explicit ProfiledPIDSubsystem(frc::ProfiledPIDController controller);
void Periodic() override;
/**
* Uses the output from the ProfiledPIDController.
*
* @param output the output of the ProfiledPIDController
*/
virtual void UseOutput(double output, State state) = 0;
/**
* Returns the goal used by the ProfiledPIDController.
*
* @return the goal to be used by the controller
*/
virtual State GetGoal() = 0;
/**
* Returns the measurement of the process variable used by the
* ProfiledPIDController.
*
* @return the measurement of the process variable
*/
virtual units::meter_t GetMeasurement() = 0;
/**
* Enables the PID control. Resets the controller.
*/
virtual void Enable();
/**
* Disables the PID control. Sets output to zero.
*/
virtual void Disable();
/**
* Returns the ProfiledPIDController.
*
* @return The controller.
*/
frc::ProfiledPIDController& GetController();
protected:
frc::ProfiledPIDController m_controller;
bool m_enabled;
};
} // namespace frc2

View File

@@ -1,50 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <wpi/SmallVector.h>
#include "CommandBase.h"
#include "CommandHelper.h"
#include "SetUtilities.h"
namespace frc2 {
/**
* Schedules the given commands when this command is initialized, and ends when
* all the commands are no longer scheduled. Useful for forking off from
* CommandGroups. If this command is interrupted, it will cancel all of the
* commands.
*/
class ProxyScheduleCommand
: public CommandHelper<CommandBase, ProxyScheduleCommand> {
public:
/**
* Creates a new ProxyScheduleCommand that schedules the given commands when
* initialized, and ends when they are all no longer scheduled.
*
* @param toSchedule the commands to schedule
*/
explicit ProxyScheduleCommand(wpi::ArrayRef<Command*> toSchedule);
ProxyScheduleCommand(ProxyScheduleCommand&& other) = default;
ProxyScheduleCommand(const ProxyScheduleCommand& other) = default;
void Initialize() override;
void End(bool interrupted) override;
void Execute() override;
bool IsFinished() override;
private:
wpi::SmallVector<Command*, 4> m_toSchedule;
bool m_finished{false};
};
} // namespace frc2

View File

@@ -1,148 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#include <functional>
#include <memory>
#include <units/units.h>
#include "CommandBase.h"
#include "CommandHelper.h"
#include "frc/controller/PIDController.h"
#include "frc/controller/RamseteController.h"
#include "frc/geometry/Pose2d.h"
#include "frc/kinematics/DifferentialDriveKinematics.h"
#include "frc/trajectory/Trajectory.h"
#include "frc2/Timer.h"
#pragma once
namespace frc2 {
/**
* A command that uses a RAMSETE controller to follow a trajectory
* with a differential drive.
*
* <p>The command handles trajectory-following, PID calculations, and
* feedforwards internally. This is intended to be a more-or-less "complete
* solution" that can be used by teams without a great deal of controls
* expertise.
*
* <p>Advanced teams seeking more flexibility (for example, those who wish to
* use the onboard PID functionality of a "smart" motor controller) may use the
* secondary constructor that omits the PID and feedforward functionality,
* returning only the raw wheel speeds from the RAMSETE controller.
*
* @see RamseteController
* @see Trajectory
*/
class RamseteCommand : public CommandHelper<CommandBase, RamseteCommand> {
using voltsecondspermeter =
units::compound_unit<units::volt, units::second,
units::inverse<units::meter>>;
using voltsecondssquaredpermeter =
units::compound_unit<units::volt, units::squared<units::second>,
units::inverse<units::meter>>;
public:
/**
* Constructs a new RamseteCommand that, when executed, will follow the
* provided trajectory. PID control and feedforward are handled internally,
* and outputs are scaled -1 to 1 for easy consumption by speed controllers.
*
* <p>Note: The controller will *not* set the outputVolts to zero upon
* completion of the path - this is left to the user, since it is not
* appropriate for paths with nonstationary endstates.
*
* @param trajectory The trajectory to follow.
* @param pose A function that supplies the robot pose - use one of
* the odometry classes to provide this.
* @param controller The RAMSETE controller used to follow the
* trajectory.
* @param ks Constant feedforward term for the robot drive.
* @param kv Velocity-proportional feedforward term for the robot
* drive.
* @param ka Acceleration-proportional feedforward term for the
* robot drive.
* @param kinematics The kinematics for the robot drivetrain.
* @param leftSpeed A function that supplies the speed of the left side
* of the robot drive.
* @param rightSpeed A function that supplies the speed of the right side
* of the robot drive.
* @param leftController The PIDController for the left side of the robot
* drive.
* @param rightController The PIDController for the right side of the robot
* drive.
* @param output A function that consumes the computed left and right
* outputs (in volts) for the robot drive.
* @param requirements The subsystems to require.
*/
RamseteCommand(frc::Trajectory trajectory, std::function<frc::Pose2d()> pose,
frc::RamseteController controller, units::volt_t ks,
units::unit_t<voltsecondspermeter> kv,
units::unit_t<voltsecondssquaredpermeter> ka,
frc::DifferentialDriveKinematics kinematics,
std::function<units::meters_per_second_t()> leftSpeed,
std::function<units::meters_per_second_t()> rightSpeed,
frc2::PIDController leftController,
frc2::PIDController rightController,
std::function<void(units::volt_t, units::volt_t)> output,
std::initializer_list<Subsystem*> requirements);
/**
* Constructs a new RamseteCommand that, when executed, will follow the
* provided trajectory. Performs no PID control and calculates no
* feedforwards; outputs are the raw wheel speeds from the RAMSETE controller,
* and will need to be converted into a usable form by the user.
*
* @param trajectory The trajectory to follow.
* @param pose A function that supplies the robot pose - use one of
* the odometry classes to provide this.
* @param controller The RAMSETE controller used to follow the
* trajectory.
* @param kinematics The kinematics for the robot drivetrain.
* @param output A function that consumes the computed left and right
* outputs (in volts) for the robot drive.
* @param requirements The subsystems to require.
*/
RamseteCommand(frc::Trajectory trajectory, std::function<frc::Pose2d()> pose,
frc::RamseteController controller,
frc::DifferentialDriveKinematics kinematics,
std::function<void(units::meters_per_second_t,
units::meters_per_second_t)>
output,
std::initializer_list<Subsystem*> requirements);
void Initialize() override;
void Execute() override;
void End(bool interrupted) override;
bool IsFinished() override;
private:
frc::Trajectory m_trajectory;
std::function<frc::Pose2d()> m_pose;
frc::RamseteController m_controller;
const units::volt_t m_ks;
const units::unit_t<voltsecondspermeter> m_kv;
const units::unit_t<voltsecondssquaredpermeter> m_ka;
frc::DifferentialDriveKinematics m_kinematics;
std::function<units::meters_per_second_t()> m_leftSpeed;
std::function<units::meters_per_second_t()> m_rightSpeed;
std::unique_ptr<frc2::PIDController> m_leftController;
std::unique_ptr<frc2::PIDController> m_rightController;
std::function<void(units::volt_t, units::volt_t)> m_outputVolts;
std::function<void(units::meters_per_second_t, units::meters_per_second_t)>
m_outputVel;
Timer m_timer;
units::second_t m_prevTime;
frc::DifferentialDriveWheelSpeeds m_prevSpeeds;
bool m_usePID;
};
} // namespace frc2

View File

@@ -1,41 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include "CommandBase.h"
#include "CommandHelper.h"
namespace frc2 {
/**
* A command that runs a Runnable continuously. Has no end condition as-is;
* either subclass it or use Command.WithTimeout() or
* Command.WithInterrupt() to give it one. If you only wish
* to execute a Runnable once, use InstantCommand.
*/
class RunCommand : public CommandHelper<CommandBase, RunCommand> {
public:
/**
* Creates a new RunCommand. The Runnable will be run continuously until the
* command ends. Does not run when disabled.
*
* @param toRun the Runnable to run
* @param requirements the subsystems to require
*/
RunCommand(std::function<void()> toRun,
std::initializer_list<Subsystem*> requirements);
RunCommand(RunCommand&& other) = default;
RunCommand(const RunCommand& other) = default;
void Execute();
protected:
std::function<void()> m_toRun;
};
} // namespace frc2

View File

@@ -1,46 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <wpi/SmallVector.h>
#include "CommandBase.h"
#include "CommandHelper.h"
#include "SetUtilities.h"
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.
*/
class ScheduleCommand : public CommandHelper<CommandBase, ScheduleCommand> {
public:
/**
* Creates a new ScheduleCommand that schedules the given commands when
* initialized.
*
* @param toSchedule the commands to schedule
*/
explicit ScheduleCommand(wpi::ArrayRef<Command*> toSchedule);
ScheduleCommand(ScheduleCommand&& other) = default;
ScheduleCommand(const ScheduleCommand& other) = default;
void Initialize() override;
bool IsFinished() override;
bool RunsWhenDisabled() const override;
private:
wpi::SmallVector<Command*, 4> m_toSchedule;
};
} // namespace frc2

View File

@@ -1,153 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#ifdef _WIN32
#pragma warning(push)
#pragma warning(disable : 4521)
#endif
#include <memory>
#include <unordered_map>
#include <utility>
#include <vector>
#include "CommandBase.h"
#include "CommandGroupBase.h"
#include "PrintCommand.h"
namespace frc2 {
template <typename Key>
/**
* 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.
*
* <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.
*/
class SelectCommand : public CommandHelper<CommandBase, SelectCommand<Key>> {
public:
/**
* Creates a new selectcommand.
*
* @param commands the map of commands to choose from
* @param selector the selector to determine which command to run
*/
template <class... Types,
typename = std::enable_if_t<std::conjunction_v<
std::is_base_of<Command, std::remove_reference_t<Types>>...>>>
SelectCommand(std::function<Key()> selector,
std::pair<Key, Types>... commands)
: m_selector{std::move(selector)} {
std::vector<std::pair<Key, std::unique_ptr<Command>>> foo;
((void)foo.emplace_back(commands.first,
std::make_unique<std::remove_reference_t<Types>>(
std::move(commands.second))),
...);
for (auto&& command : foo) {
if (!CommandGroupBase::RequireUngrouped(command.second)) {
return;
}
}
for (auto&& command : foo) {
this->AddRequirements(command.second->GetRequirements());
m_runsWhenDisabled &= command.second->RunsWhenDisabled();
m_commands.emplace(std::move(command.first), std::move(command.second));
}
}
SelectCommand(
std::function<Key()> selector,
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;
}
}
for (auto&& command : commands) {
this->AddRequirements(command.second->GetRequirements());
m_runsWhenDisabled &= command.second->RunsWhenDisabled();
m_commands.emplace(std::move(command.first), std::move(command.second));
}
}
// No copy constructors for command groups
SelectCommand(const SelectCommand& other) = delete;
// Prevent template expansion from emulating copy ctor
SelectCommand(SelectCommand&) = delete;
/**
* Creates a new selectcommand.
*
* @param toRun a supplier providing the command to run
*/
explicit SelectCommand(std::function<Command*()> toRun) : m_toRun{toRun} {}
SelectCommand(SelectCommand&& other) = default;
void Initialize() override;
void Execute() override { m_selectedCommand->Execute(); }
void End(bool interrupted) override {
return m_selectedCommand->End(interrupted);
}
bool IsFinished() override { return m_selectedCommand->IsFinished(); }
bool RunsWhenDisabled() const override { return m_runsWhenDisabled; }
protected:
std::unique_ptr<Command> TransferOwnership() && override {
return std::make_unique<SelectCommand>(std::move(*this));
}
private:
std::unordered_map<Key, std::unique_ptr<Command>> m_commands;
std::function<Key()> m_selector;
std::function<Command*()> m_toRun;
Command* m_selectedCommand;
bool m_runsWhenDisabled = true;
};
template <typename T>
void SelectCommand<T>::Initialize() {
if (m_selector) {
auto find = m_commands.find(m_selector());
if (find == m_commands.end()) {
m_selectedCommand = new PrintCommand(
"SelectCommand selector value does not correspond to any command!");
return;
}
m_selectedCommand = find->second.get();
} else {
m_selectedCommand = m_toRun();
}
m_selectedCommand->Initialize();
}
} // namespace frc2
#ifdef _WIN32
#pragma warning(pop)
#endif

View File

@@ -1,104 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#ifdef _WIN32
#pragma warning(push)
#pragma warning(disable : 4521)
#endif
#include <limits>
#include <memory>
#include <utility>
#include <vector>
#include <wpi/ArrayRef.h>
#include "CommandGroupBase.h"
#include "CommandHelper.h"
#include "frc/ErrorBase.h"
#include "frc/WPIErrors.h"
namespace frc2 {
const size_t invalid_index = std::numeric_limits<size_t>::max();
/**
* A CommandGroups that runs a list of commands in sequence.
*
* <p>As a rule, CommandGroups require the union of the requirements of their
* component commands.
*/
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
* finishes.
*
* @param commands the commands to include in this group.
*/
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
* finishes.
*
* @param commands the commands to include in this group.
*/
template <class... Types,
typename = std::enable_if_t<std::conjunction_v<
std::is_base_of<Command, std::remove_reference_t<Types>>...>>>
explicit SequentialCommandGroup(Types&&... commands) {
AddCommands(std::forward<Types>(commands)...);
}
SequentialCommandGroup(SequentialCommandGroup&& other) = default;
// No copy constructors for command groups
SequentialCommandGroup(const SequentialCommandGroup&) = delete;
// Prevent template expansion from emulating copy ctor
SequentialCommandGroup(SequentialCommandGroup&) = delete;
template <class... Types,
typename = std::enable_if_t<std::conjunction_v<
std::is_base_of<Command, std::remove_reference_t<Types>>...>>>
void AddCommands(Types&&... commands) {
std::vector<std::unique_ptr<Command>> foo;
((void)foo.emplace_back(std::make_unique<std::remove_reference_t<Types>>(
std::forward<Types>(commands))),
...);
AddCommands(std::move(foo));
}
void Initialize() override;
void Execute() override;
void End(bool interrupted) override;
bool IsFinished() override;
bool RunsWhenDisabled() const override;
private:
void AddCommands(std::vector<std::unique_ptr<Command>>&& commands) final;
wpi::SmallVector<std::unique_ptr<Command>, 4> m_commands;
size_t m_currentCommandIndex{invalid_index};
bool m_runWhenDisabled{true};
};
} // namespace frc2
#ifdef _WIN32
#pragma warning(pop)
#endif

View File

@@ -1,29 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <wpi/ArrayRef.h>
#include <wpi/SmallVector.h>
namespace frc2 {
template <typename T>
void SetInsert(wpi::SmallVectorImpl<T*>& vector, wpi::ArrayRef<T*> toAdd) {
for (auto addCommand : toAdd) {
bool exists = false;
for (auto existingCommand : vector) {
if (addCommand == existingCommand) {
exists = true;
break;
}
}
if (!exists) {
vector.emplace_back(addCommand);
}
}
}
} // namespace frc2

View File

@@ -1,46 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include "CommandBase.h"
#include "CommandHelper.h"
namespace frc2 {
/**
* A command that runs a given runnable when it is initalized, and another
* runnable when it ends. Useful for running and then stopping a motor, or
* extending and then retracting a solenoid. Has no end condition as-is; either
* subclass it or use Command.WithTimeout() or Command.WithInterrupt() to give
* it one.
*/
class StartEndCommand : public CommandHelper<CommandBase, StartEndCommand> {
public:
/**
* Creates a new StartEndCommand. Will run the given runnables when the
* command starts and when it ends.
*
* @param onInit the Runnable to run on command init
* @param onEnd the Runnable to run on command end
* @param requirements the subsystems required by this command
*/
StartEndCommand(std::function<void()> onInit, std::function<void()> onEnd,
std::initializer_list<Subsystem*> requirements);
StartEndCommand(StartEndCommand&& other) = default;
StartEndCommand(const StartEndCommand& other);
void Initialize() override;
void End(bool interrupted) override;
protected:
std::function<void()> m_onInit;
std::function<void()> m_onEnd;
};
} // namespace frc2

View File

@@ -1,88 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <frc2/command/CommandScheduler.h>
#include <utility>
namespace frc2 {
class Command;
/**
* A robot subsystem. Subsystems are the basic unit of robot organization in
* the Command-based framework; they encapsulate low-level hardware objects
* (motor controllers, sensors, etc) and provide methods through which they can
* be used by Commands. Subsystems are used by the CommandScheduler's resource
* management system to ensure multiple robot actions are not "fighting" over
* the same hardware; Commands that use a subsystem should include that
* subsystem in their GetRequirements() method, and resources used within a
* subsystem should generally remain encapsulated and not be shared by other
* parts of the robot.
*
* <p>Subsystems must be registered with the scheduler with the
* CommandScheduler.RegisterSubsystem() method in order for the
* Periodic() method to be called. It is recommended that this method be called
* from the constructor of users' Subsystem implementations. The
* SubsystemBase class offers a simple base for user implementations
* that handles this.
*
* @see Command
* @see CommandScheduler
* @see SubsystemBase
*/
class Subsystem {
public:
~Subsystem();
/**
* This method is called periodically by the CommandScheduler. Useful for
* updating subsystem-specific state that you don't want to offload to a
* Command. Teams should try to be consistent within their own codebases
* about which responsibilities will be handled by Commands, and which will be
* handled here.
*/
virtual void Periodic();
/**
* Sets the default Command of the subsystem. The default command will be
* automatically scheduled when no other commands are scheduled that require
* the subsystem. Default commands should generally not end on their own, i.e.
* their IsFinished() method should always return false. Will automatically
* register this subsystem with the CommandScheduler.
*
* @param defaultCommand the default command to associate with this subsystem
*/
template <class T, typename = std::enable_if_t<std::is_base_of_v<
Command, std::remove_reference_t<T>>>>
void SetDefaultCommand(T&& defaultCommand) {
CommandScheduler::GetInstance().SetDefaultCommand(
this, std::forward<T>(defaultCommand));
}
/**
* Gets the default command for this subsystem. Returns null if no default
* command is currently associated with the subsystem.
*
* @return the default command associated with this subsystem
*/
Command* GetDefaultCommand() const;
/**
* Returns the command currently running on this subsystem. Returns null if
* no command is currently scheduled that requires this subsystem.
*
* @return the scheduled command currently requiring this subsystem
*/
Command* GetCurrentCommand() const;
/**
* Registers this subsystem with the CommandScheduler, allowing its
* Periodic() method to be called when the scheduler runs.
*/
void Register();
};
} // namespace frc2

View File

@@ -1,68 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <frc/smartdashboard/Sendable.h>
#include <frc/smartdashboard/SendableHelper.h>
#include <string>
#include "Subsystem.h"
namespace frc2 {
/**
* A base for subsystems that handles registration in the constructor, and
* provides a more intuitive method for setting the default command.
*/
class SubsystemBase : public Subsystem,
public frc::Sendable,
public frc::SendableHelper<SubsystemBase> {
public:
void InitSendable(frc::SendableBuilder& builder) override;
/**
* Gets the name of this Subsystem.
*
* @return Name
*/
std::string GetName() const;
/**
* Sets the name of this Subsystem.
*
* @param name name
*/
void SetName(const wpi::Twine& name);
/**
* Gets the subsystem name of this Subsystem.
*
* @return Subsystem name
*/
std::string GetSubsystem() const;
/**
* Sets the subsystem name of this Subsystem.
*
* @param subsystem subsystem name
*/
void SetSubsystem(const wpi::Twine& name);
/**
* Associate a Sendable with this Subsystem.
* Also update the child's name.
*
* @param name name to give child
* @param child sendable
*/
void AddChild(std::string name, frc::Sendable* child);
protected:
SubsystemBase();
};
} // namespace frc2

View File

@@ -1,55 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#include <frc/trajectory/TrapezoidProfile.h>
#include <frc2/Timer.h>
#include <functional>
#include "CommandBase.h"
#include "CommandHelper.h"
#pragma once
namespace frc2 {
/**
* A command that runs a TrapezoidProfile. Useful for smoothly controlling
* mechanism motion.
*
* @see TrapezoidProfile
*/
class TrapezoidProfileCommand
: public CommandHelper<CommandBase, TrapezoidProfileCommand> {
public:
/**
* Creates a new TrapezoidProfileCommand that will execute the given
* TrapezoidalProfile. Output will be piped to the provided consumer function.
*
* @param profile The motion profile to execute.
* @param output The consumer for the profile output.
*/
TrapezoidProfileCommand(
frc::TrapezoidProfile profile,
std::function<void(frc::TrapezoidProfile::State)> output,
std::initializer_list<Subsystem*> requirements);
void Initialize() override;
void Execute() override;
void End(bool interrupted) override;
bool IsFinished() override;
private:
frc::TrapezoidProfile m_profile;
std::function<void(frc::TrapezoidProfile::State)> m_output;
Timer m_timer;
};
} // namespace frc2

View File

@@ -1,51 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <units/units.h>
#include <wpi/Twine.h>
#include "CommandBase.h"
#include "CommandHelper.h"
#include "frc2/Timer.h"
namespace frc2 {
/**
* A command that does nothing but takes a specified amount of time to finish.
* Useful for CommandGroups. Can also be subclassed to make a command with an
* internal timer.
*/
class WaitCommand : public CommandHelper<CommandBase, WaitCommand> {
public:
/**
* Creates a new WaitCommand. This command will do nothing, and end after the
* specified duration.
*
* @param duration the time to wait
*/
explicit WaitCommand(units::second_t duration);
WaitCommand(WaitCommand&& other) = default;
WaitCommand(const WaitCommand& other) = default;
void Initialize() override;
void End(bool interrupted) override;
bool IsFinished() override;
bool RunsWhenDisabled() const override;
protected:
Timer m_timer;
private:
units::second_t m_duration;
};
} // namespace frc2

View File

@@ -1,52 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include "CommandBase.h"
#include "frc/Timer.h"
#include "frc2/command/CommandHelper.h"
namespace frc2 {
/**
* A command that does nothing but ends after a specified match time or
* condition. Useful for CommandGroups.
*/
class WaitUntilCommand : public CommandHelper<CommandBase, WaitUntilCommand> {
public:
/**
* Creates a new WaitUntilCommand that ends after a given condition becomes
* true.
*
* @param condition the condition to determine when to end
*/
explicit WaitUntilCommand(std::function<bool()> condition);
/**
* Creates a new WaitUntilCommand that ends after a given match time.
*
* <p>NOTE: The match timer used for this command is UNOFFICIAL. Using this
* command does NOT guarantee that the time at which the action is performed
* will be judged to be legal by the referees. When in doubt, add a safety
* factor or time the action manually.
*
* @param time the match time after which to end, in seconds
*/
explicit WaitUntilCommand(double time);
WaitUntilCommand(WaitUntilCommand&& other) = default;
WaitUntilCommand(const WaitUntilCommand& other) = default;
bool IsFinished() override;
bool RunsWhenDisabled() const override;
private:
std::function<bool()> m_condition;
};
} // namespace frc2

View File

@@ -1,207 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <utility>
#include "Trigger.h"
namespace frc2 {
class Command;
/**
* A class used to bind command scheduling to button presses. Can be composed
* with other buttons with the operators in Trigger.
*
* @see Trigger
*/
class Button : public Trigger {
public:
/**
* Create a new button that is pressed when the given condition is true.
*
* @param isActive Whether the button is pressed.
*/
explicit Button(std::function<bool()> isPressed);
/**
* Create a new button that is pressed active (default constructor) - activity
* can be further determined by subclass code.
*/
Button() = default;
/**
* Binds a command to start when the button is pressed. Takes a
* raw pointer, and so is non-owning; users are responsible for the lifespan
* of the command.
*
* @param command The command to bind.
* @param interruptible Whether the command should be interruptible.
* @return The trigger, for chained calls.
*/
Button WhenPressed(Command* command, bool interruptible = true);
/**
* Binds a command to start when the button is pressed. Transfers
* command ownership to the button scheduler, so the user does not have to
* worry about lifespan - rvalue refs will be *moved*, lvalue refs will be
* *copied.*
*
* @param command The command to bind.
* @param interruptible Whether the command should be interruptible.
* @return The trigger, for chained calls.
*/
template <class T, typename = std::enable_if_t<std::is_base_of_v<
Command, std::remove_reference_t<T>>>>
Button WhenPressed(T&& command, bool interruptible = true) {
WhenActive(std::forward<T>(command), interruptible);
return *this;
}
/**
* Binds a runnable to execute when the button is pressed.
*
* @param toRun the runnable to execute.
*/
Button WhenPressed(std::function<void()> toRun);
/**
* Binds a command to be started repeatedly while the button is pressed, and
* cancelled when it is released. Takes a raw pointer, and so is non-owning;
* users are responsible for the lifespan of the command.
*
* @param command The command to bind.
* @param interruptible Whether the command should be interruptible.
* @return The button, for chained calls.
*/
Button WhileHeld(Command* command, bool interruptible = true);
/**
* Binds a command to be started repeatedly while the button is pressed, and
* cancelled when it is released. Transfers command ownership to the button
* scheduler, so the user does not have to worry about lifespan - rvalue refs
* will be *moved*, lvalue refs will be *copied.*
*
* @param command The command to bind.
* @param interruptible Whether the command should be interruptible.
* @return The button, for chained calls.
*/
template <class T, typename = std::enable_if_t<std::is_base_of_v<
Command, std::remove_reference_t<T>>>>
Button WhileHeld(T&& command, bool interruptible = true) {
WhileActiveContinous(std::forward<T>(command), interruptible);
return *this;
}
/**
* Binds a runnable to execute repeatedly while the button is pressed.
*
* @param toRun the runnable to execute.
*/
Button WhileHeld(std::function<void()> toRun);
/**
* Binds a command to be started when the button is pressed, and cancelled
* when it is released. Takes a raw pointer, and so is non-owning; users are
* responsible for the lifespan of the command.
*
* @param command The command to bind.
* @param interruptible Whether the command should be interruptible.
* @return The button, for chained calls.
*/
Button WhenHeld(Command* command, bool interruptible = true);
/**
* Binds a command to be started when the button is pressed, and cancelled
* when it is released. Transfers command ownership to the button scheduler,
* so the user does not have to worry about lifespan - rvalue refs will be
* *moved*, lvalue refs will be *copied.*
*
* @param command The command to bind.
* @param interruptible Whether the command should be interruptible.
* @return The button, for chained calls.
*/
template <class T, typename = std::enable_if_t<std::is_base_of_v<
Command, std::remove_reference_t<T>>>>
Button WhenHeld(T&& command, bool interruptible = true) {
WhileActiveOnce(std::forward<T>(command), interruptible);
return *this;
}
/**
* Binds a command to start when the button is released. Takes a
* raw pointer, and so is non-owning; users are responsible for the lifespan
* of the command.
*
* @param command The command to bind.
* @param interruptible Whether the command should be interruptible.
* @return The button, for chained calls.
*/
Button WhenReleased(Command* command, bool interruptible = true);
/**
* Binds a command to start when the button is pressed. Transfers
* command ownership to the button scheduler, so the user does not have to
* worry about lifespan - rvalue refs will be *moved*, lvalue refs will be
* *copied.*
*
* @param command The command to bind.
* @param interruptible Whether the command should be interruptible.
* @return The button, for chained calls.
*/
template <class T, typename = std::enable_if_t<std::is_base_of_v<
Command, std::remove_reference_t<T>>>>
Button WhenReleased(T&& command, bool interruptible = true) {
WhenInactive(std::forward<T>(command), interruptible);
return *this;
}
/**
* Binds a runnable to execute when the button is released.
*
* @param toRun the runnable to execute.
*/
Button WhenReleased(std::function<void()> toRun);
/**
* Binds a command to start when the button is pressed, and be cancelled when
* it is pressed again. Takes a raw pointer, and so is non-owning; users are
* responsible for the lifespan of the command.
*
* @param command The command to bind.
* @param interruptible Whether the command should be interruptible.
* @return The button, for chained calls.
*/
Button ToggleWhenPressed(Command* command, bool interruptible = true);
/**
* Binds a command to start when the button is pressed, and be cancelled when
* it is pessed again. Transfers command ownership to the button scheduler,
* so the user does not have to worry about lifespan - rvalue refs will be
* *moved*, lvalue refs will be *copied.*
*
* @param command The command to bind.
* @param interruptible Whether the command should be interruptible.
* @return The button, for chained calls.
*/
template <class T, typename = std::enable_if_t<std::is_base_of_v<
Command, std::remove_reference_t<T>>>>
Button ToggleWhenPressed(T&& command, bool interruptible = true) {
ToggleWhenActive(std::forward<T>(command), interruptible);
return *this;
}
/**
* Binds a command to be cancelled when the button is pressed. Takes a
* raw pointer, and so is non-owning; users are responsible for the lifespan
* and scheduling of the command.
*
* @param command The command to bind.
* @return The button, for chained calls.
*/
Button CancelWhenPressed(Command* command);
};
} // namespace frc2

View File

@@ -1,37 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <frc/GenericHID.h>
#include "Button.h"
namespace frc2 {
/**
* A class used to bind command scheduling to joystick button presses. Can be
* composed with other buttons with the operators in Trigger.
*
* @see Trigger
*/
class JoystickButton : public Button {
public:
/**
* Creates a JoystickButton that commands can be bound to.
*
* @param joystick The joystick on which the button is located.
* @param buttonNumber The number of the button on the joystic.
*/
explicit JoystickButton(frc::GenericHID* joystick, int buttonNumber)
: m_joystick{joystick}, m_buttonNumber{buttonNumber} {}
bool Get() const override { return m_joystick->GetRawButton(m_buttonNumber); }
private:
frc::GenericHID* m_joystick;
int m_buttonNumber;
};
} // namespace frc2

View File

@@ -1,41 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <frc/GenericHID.h>
#include "Button.h"
namespace frc2 {
/**
* A class used to bind command scheduling to joystick POV presses. Can be
* composed with other buttons with the operators in Trigger.
*
* @see Trigger
*/
class POVButton : public Button {
public:
/**
* Creates a POVButton that commands can be bound to.
*
* @param joystick The joystick on which the button is located.
* @param angle The angle of the POV corresponding to a button press.
* @param povNumber The number of the POV on the joystick.
*/
POVButton(frc::GenericHID* joystick, int angle, int povNumber = 0)
: m_joystick{joystick}, m_angle{angle}, m_povNumber{povNumber} {}
bool Get() const override {
return m_joystick->GetPOV(m_povNumber) == m_angle;
}
private:
frc::GenericHID* m_joystick;
int m_angle;
int m_povNumber;
};
} // namespace frc2

View File

@@ -1,325 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <frc2/command/Command.h>
#include <frc2/command/CommandScheduler.h>
#include <atomic>
#include <memory>
#include <utility>
namespace frc2 {
class Command;
/**
* A class used to bind command scheduling to events. The
* Trigger class is a base for all command-event-binding classes, and so the
* methods are named fairly abstractly; for purpose-specific wrappers, see
* Button.
*
* @see Button
*/
class Trigger {
public:
/**
* Create a new trigger that is active when the given condition is true.
*
* @param isActive Whether the trigger is active.
*/
explicit Trigger(std::function<bool()> isActive)
: m_isActive{std::move(isActive)} {}
/**
* Create a new trigger that is never active (default constructor) - activity
* can be further determined by subclass code.
*/
Trigger() {
m_isActive = [] { return false; };
}
Trigger(const Trigger& other);
/**
* Returns whether the trigger is active. Can be overridden by a subclass.
*
* @return Whether the trigger is active.
*/
virtual bool Get() const { return m_isActive(); }
/**
* Binds a command to start when the trigger becomes active. Takes a
* raw pointer, and so is non-owning; users are responsible for the lifespan
* of the command.
*
* @param command The command to bind.
* @param interruptible Whether the command should be interruptible.
* @return The trigger, for chained calls.
*/
Trigger WhenActive(Command* command, bool interruptible = true);
/**
* Binds a command to start when the trigger becomes active. Transfers
* command ownership to the button scheduler, so the user does not have to
* worry about lifespan - rvalue refs will be *moved*, lvalue refs will be
* *copied.*
*
* @param command The command to bind.
* @param interruptible Whether the command should be interruptible.
* @return The trigger, for chained calls.
*/
template <class T, typename = std::enable_if_t<std::is_base_of_v<
Command, std::remove_reference_t<T>>>>
Trigger WhenActive(T&& command, bool interruptible = true) {
CommandScheduler::GetInstance().AddButton(
[pressedLast = Get(), *this,
command = std::make_unique<std::remove_reference_t<T>>(
std::forward<T>(command)),
interruptible]() mutable {
bool pressed = Get();
if (!pressedLast && pressed) {
command->Schedule(interruptible);
}
pressedLast = pressed;
});
return *this;
}
/**
* Binds a runnable to execute when the trigger becomes active.
*
* @param toRun the runnable to execute.
*/
Trigger WhenActive(std::function<void()> toRun);
/**
* Binds a command to be started repeatedly while the trigger is active, and
* cancelled when it becomes inactive. Takes a raw pointer, and so is
* non-owning; users are responsible for the lifespan of the command.
*
* @param command The command to bind.
* @param interruptible Whether the command should be interruptible.
* @return The trigger, for chained calls.
*/
Trigger WhileActiveContinous(Command* command, bool interruptible = true);
/**
* Binds a command to be started repeatedly while the trigger is active, and
* cancelled when it becomes inactive. Transfers command ownership to the
* button scheduler, so the user does not have to worry about lifespan -
* rvalue refs will be *moved*, lvalue refs will be *copied.*
*
* @param command The command to bind.
* @param interruptible Whether the command should be interruptible.
* @return The trigger, for chained calls.
*/
template <class T, typename = std::enable_if_t<std::is_base_of_v<
Command, std::remove_reference_t<T>>>>
Trigger WhileActiveContinous(T&& command, bool interruptible = true) {
CommandScheduler::GetInstance().AddButton(
[pressedLast = Get(), *this,
command = std::make_unique<std::remove_reference_t<T>>(
std::forward<T>(command)),
interruptible]() mutable {
bool pressed = Get();
if (pressed) {
command->Schedule(interruptible);
} else if (pressedLast && !pressed) {
command->Cancel();
}
pressedLast = pressed;
});
return *this;
}
/**
* Binds a runnable to execute repeatedly while the trigger is active.
*
* @param toRun the runnable to execute.
*/
Trigger WhileActiveContinous(std::function<void()> toRun);
/**
* Binds a command to be started when the trigger becomes active, and
* cancelled when it becomes inactive. Takes a raw pointer, and so is
* non-owning; users are responsible for the lifespan of the command.
*
* @param command The command to bind.
* @param interruptible Whether the command should be interruptible.
* @return The trigger, for chained calls.
*/
Trigger WhileActiveOnce(Command* command, bool interruptible = true);
/**
* Binds a command to be started when the trigger becomes active, and
* cancelled when it becomes inactive. Transfers command ownership to the
* button scheduler, so the user does not have to worry about lifespan -
* rvalue refs will be *moved*, lvalue refs will be *copied.*
*
* @param command The command to bind.
* @param interruptible Whether the command should be interruptible.
* @return The trigger, for chained calls.
*/
template <class T, typename = std::enable_if_t<std::is_base_of_v<
Command, std::remove_reference_t<T>>>>
Trigger WhileActiveOnce(T&& command, bool interruptible = true) {
CommandScheduler::GetInstance().AddButton(
[pressedLast = Get(), *this,
command = std::make_unique<std::remove_reference_t<T>>(
std::forward<T>(command)),
interruptible]() mutable {
bool pressed = Get();
if (!pressedLast && pressed) {
command->Schedule(interruptible);
} else if (pressedLast && !pressed) {
command->Cancel();
}
pressedLast = pressed;
});
return *this;
}
/**
* Binds a command to start when the trigger becomes inactive. Takes a
* raw pointer, and so is non-owning; users are responsible for the lifespan
* of the command.
*
* @param command The command to bind.
* @param interruptible Whether the command should be interruptible.
* @return The trigger, for chained calls.
*/
Trigger WhenInactive(Command* command, bool interruptible = true);
/**
* Binds a command to start when the trigger becomes inactive. Transfers
* command ownership to the button scheduler, so the user does not have to
* worry about lifespan - rvalue refs will be *moved*, lvalue refs will be
* *copied.*
*
* @param command The command to bind.
* @param interruptible Whether the command should be interruptible.
* @return The trigger, for chained calls.
*/
template <class T, typename = std::enable_if_t<std::is_base_of_v<
Command, std::remove_reference_t<T>>>>
Trigger WhenInactive(T&& command, bool interruptible = true) {
CommandScheduler::GetInstance().AddButton(
[pressedLast = Get(), *this,
command = std::make_unique<std::remove_reference_t<T>>(
std::forward<T>(command)),
interruptible]() mutable {
bool pressed = Get();
if (pressedLast && !pressed) {
command->Schedule(interruptible);
}
pressedLast = pressed;
});
return *this;
}
/**
* Binds a runnable to execute when the trigger becomes inactive.
*
* @param toRun the runnable to execute.
*/
Trigger WhenInactive(std::function<void()> toRun);
/**
* Binds a command to start when the trigger becomes active, and be cancelled
* when it again becomes active. Takes a raw pointer, and so is non-owning;
* users are responsible for the lifespan of the command.
*
* @param command The command to bind.
* @param interruptible Whether the command should be interruptible.
* @return The trigger, for chained calls.
*/
Trigger ToggleWhenActive(Command* command, bool interruptible = true);
/**
* Binds a command to start when the trigger becomes active, and be cancelled
* when it again becomes active. Transfers command ownership to the button
* scheduler, so the user does not have to worry about lifespan - rvalue refs
* will be *moved*, lvalue refs will be *copied.*
*
* @param command The command to bind.
* @param interruptible Whether the command should be interruptible.
* @return The trigger, for chained calls.
*/
template <class T, typename = std::enable_if_t<std::is_base_of_v<
Command, std::remove_reference_t<T>>>>
Trigger ToggleWhenActive(T&& command, bool interruptible = true) {
CommandScheduler::GetInstance().AddButton(
[pressedLast = Get(), *this,
command = std::make_unique<std::remove_reference_t<T>>(
std::forward<T>(command)),
interruptible]() mutable {
bool pressed = Get();
if (!pressedLast && pressed) {
if (command->IsScheduled()) {
command->Cancel();
} else {
command->Schedule(interruptible);
}
}
pressedLast = pressed;
});
return *this;
}
/**
* Binds a command to be cancelled when the trigger becomes active. Takes a
* raw pointer, and so is non-owning; users are responsible for the lifespan
* and scheduling of the command.
*
* @param command The command to bind.
* @return The trigger, for chained calls.
*/
Trigger CancelWhenActive(Command* command);
/**
* Composes two triggers with logical AND.
*
* @return A trigger which is active when both component triggers are active.
*/
Trigger operator&&(Trigger rhs) {
return Trigger([*this, rhs] { return Get() && rhs.Get(); });
}
/**
* Composes two triggers with logical OR.
*
* @return A trigger which is active when either component trigger is active.
*/
Trigger operator||(Trigger rhs) {
return Trigger([*this, rhs] { return Get() || rhs.Get(); });
}
/**
* Composes a trigger with logical NOT.
*
* @return A trigger which is active when the component trigger is inactive,
* and vice-versa.
*/
Trigger operator!() {
return Trigger([*this] { return !Get(); });
}
private:
std::function<bool()> m_isActive;
};
} // namespace frc2