Class CommandScheduler
Defined in File command_scheduler.hpp
Nested Relationships
Nested Types
Class Documentation
-
class CommandScheduler
Class for handling all the commands you would like to currently run. Interfaces with the Subsystem and Command classes to provide a means of safely scheduling multiple Commands and Subsystems. Checks are provided while scheduling such that multiple commands that require the same subsystem cannot run at the same time. Suppose for example that you have a Command that moves a mechanical arm Subsystem to some position and another Command that moves the same arm to a different position. Obvious issues arise if one attempts to tell the Subsystem to do two things at once. Using this class will disallow these two Commands from being executed at the same time.
For the the above reasons, you cannot map the same command instance to two different input states at the same time. You must declare a separate instance of the command (these can be the same class) for each mapping, or use a ComprisedCommand with your own scheduling logic.
This class contains a map of Subsystems -> Commands. The Subsystems will be refreshed each time the CommandScheduler is ran. If there are commands associated with the Subsystem, the CommandScheduler will execute these commands as well. Additional less important features are explained in more detail in the function definitions.
The goal of this class is for the user to interace directly as little as possible. Aside from calling
run
each time to update the scheduler, the user should be interacting with the Command, ComprisedCommand, Subsystem, and CommandMapper classes to add and remove commands from the scheduler.The main use case will be to be refreshing all the main subsystems running on the robot. You should access the main scheduler via the global
tap::Drivers *
instance, which should have an instance of aCommandScheduler
calledcommandScheduler
. The below example code registers a subsystem (sub
) and adds a command (cmd
) to the scheduler. Then the scheduler is run over and over, in a loop.// A class that has Subsystem as a base class. CoolSubsystem sub; // A class that has Command as a base class that requires // the subsystem above. In the constructor of the ControlCoolCommand, // you must call `addSubsystemRequirement(sub)`, where `sub` is the // `CoolSubsystem` defined above. ControlCoolCommand cmd(&sub); drivers->commandScheduler.registerSubsystem(&sub); drivers->commandScheduler.addCommand(&cmd); while (1) { // The subsystem will refresh forever and the command will execute until it // is finished. drivers->commandScheduler.run(); }
The second use case for a CommandScheduler is in the ComprisedCommand class. Here, you utilize the CommandScheduler to coordinate multiple commands inside a single command. The usage is exactly the same as using the main CommandScheduler.
Public Functions
-
CommandScheduler(Drivers *drivers, bool masterScheduler = false, SafeDisconnectFunction *safeDisconnectFunction = &CommandScheduler::defaultSafeDisconnectFunction)
-
~CommandScheduler()
-
void run()
Calls the
refresh()
function for all Subsystems and the associatedexecute()
function for all Commands. A Subsystem is guarenteed to be refreshed no more than one time each time the mainScheduler’s run function is called. The same goes for a Command. This includes even if multiple CommandSchedulers are running in ComprisedCommands that have shared Subsystems.If any Subsystem that is in the scheduler does not have a Command controlling it but does have a default command (via the Subsystem’s
getDefaultCommand()
), the default command is added to the scheduler.If any Command is finished after execution, the Command is removed from the scheduler. The Command’s
end()
function is called, passing inisInterrupted = false
.Note
checks the run time of the scheduler. An error is added to the error handler if the time is greater than
MAX_ALLOWABLE_SCHEDULER_RUNTIME
(in microseconds).
-
void addCommand(Command *commandToAdd)
Attempts to add a Command to the scheduler. There are a number of ways this function can fail. If failure does occur, an error will be added to the error handler.
These are the following reasons why adding a Command fails:
The commandToAdd is
nullptr
The commandToAdd has no Subsystem requirements.
The commandToAdd has Subsystems not in the CommandScheduler.
If a Command is successfully added to the CommandScheduler, any Subsystems that the commandToAdd requires that have Commands running will be ended (and the interrupted flag for that Command set to
true
).If a Command is successfully added, the Command’s
initialize()
function will be called.Note
If the
commandToAdd
was already scheduled, it will be interrupted (itsend()
will be called) and then the command will be rescheduled.- Parameters:
commandToAdd – [in] the Command to be added to the scheduler.
-
void removeCommand(Command *command, bool interrupted)
Removes the given Command completely from the CommandScheduler. This means removing all instances of the command pointer from the Subsystem -> Command map (since a single Subsystem can map to multiple Commands).
-
bool isCommandScheduled(const Command *command) const
- Returns:
true
if the CommandScheduler contains the requrested Command.false
otherwise.
-
void registerSubsystem(Subsystem *subsystem)
Adds the given Subsystem to the CommandScheduler. The subsystem is added with the currently scheduled Command as
nullptr
.- Parameters:
subsystem – [in] the Subsystem to add. Must be not
nullptr
and not registered already (check viaisSubsystemRegistered()
), otherwise an error is added to the error handler.
-
void setSafeDisconnectFunction(SafeDisconnectFunction *func)
Set the SafeDisconnectFunction to the given function.
- Parameters:
func – [in] the function that the CommandScheduler will use to determine what constitutes a “disconnected” state.
-
bool isSubsystemRegistered(const Subsystem *subsystem) const
- Parameters:
subsystem – [in] the subsystem to check
- Returns:
true
if the Subsystem is already scheduled,false
otherwise.
-
void runAllHardwareTests()
Runs all hardware tests from subsystems that have a test command.
-
void runHardwareTest(const Subsystem *subsystem)
Runs the hardware test command, if available, for the specific subsystem.
- Parameters:
subsystem – [in] the subsystem to run
-
void stopAllHardwareTests()
Stop all hardware tests from subsystems that have a running test command.
-
void stopHardwareTest(const Subsystem *subsystem)
Stops the hardware test command, if running, for the specific subsystem.
- Parameters:
subsystem – [in] the subsystem to stop
-
int countRunningHardwareTests()
- Returns:
the count of subsystems currently running a test.
-
bool isRunningTest(const Subsystem *subsystem)
- Parameters:
subsystem – [in] the subsystem to check
- Returns:
true
if the test command is running,false
otherwise.
-
bool hasPassedTest(const Subsystem *subsystem)
- Parameters:
subsystem – [in] the subsystem to check
- Returns:
true
if the test command has passed,false
otherwise.
-
int subsystemListSize() const
- Returns:
The number of subsystems registered with the scheduler.
-
int commandListSize() const
- Returns:
The number of commands added in the scheduler.
-
CommandIterator cmdMapBegin()
-
CommandIterator cmdMapEnd()
-
SubsystemIterator subMapBegin()
-
SubsystemIterator subMapEnd()
-
inline subsystem_scheduler_bitmap_t getRegisteredSubsystemBitmap() const
-
inline command_scheduler_bitmap_t getAddedCommandBitmap() const
Public Static Functions
-
struct CommandIterator
Iterator used for looking through the commands added to the scheduler
Public Types
-
using iterator_category = std::forward_iterator_tag
-
using difference_type = std::ptrdiff_t
Public Functions
-
CommandIterator(CommandScheduler *scheduler, int i)
-
CommandIterator &operator++()
-
CommandIterator operator++(int)
Friends
-
friend bool operator==(const CommandIterator &a, const CommandIterator &b)
-
friend bool operator!=(const CommandIterator &a, const CommandIterator &b)
-
using iterator_category = std::forward_iterator_tag
-
struct SubsystemIterator
Iterator used for looking through the subsystems registered in the scheduler
Public Types
-
using iterator_category = std::forward_iterator_tag
-
using difference_type = std::ptrdiff_t
Public Functions
-
SubsystemIterator(CommandScheduler *scheduler, int i)
-
SubsystemIterator &operator++()
-
SubsystemIterator operator++(int)
Friends
-
friend bool operator==(const SubsystemIterator &a, const SubsystemIterator &b)
-
friend bool operator!=(const SubsystemIterator &a, const SubsystemIterator &b)
-
using iterator_category = std::forward_iterator_tag
-
CommandScheduler(Drivers *drivers, bool masterScheduler = false, SafeDisconnectFunction *safeDisconnectFunction = &CommandScheduler::defaultSafeDisconnectFunction)