2013-12-15 18:30:16 -05:00
|
|
|
/*----------------------------------------------------------------------------*/
|
2017-08-23 22:06:13 -07:00
|
|
|
/* Copyright (c) 2011-2017 FIRST. All Rights Reserved. */
|
2013-12-15 18:30:16 -05:00
|
|
|
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
2016-01-02 03:02:34 -08:00
|
|
|
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
|
|
|
|
/* the project. */
|
2013-12-15 18:30:16 -05:00
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
#include "Commands/Command.h"
|
2016-09-25 16:50:13 -07:00
|
|
|
|
2016-05-20 17:30:37 -07:00
|
|
|
#include <typeinfo>
|
2016-09-25 16:50:13 -07:00
|
|
|
|
2013-12-15 18:30:16 -05:00
|
|
|
#include "Commands/CommandGroup.h"
|
|
|
|
|
#include "Commands/Scheduler.h"
|
2014-08-08 17:05:49 -04:00
|
|
|
#include "RobotState.h"
|
2013-12-15 18:30:16 -05:00
|
|
|
#include "Timer.h"
|
|
|
|
|
#include "WPIErrors.h"
|
|
|
|
|
|
2016-11-01 22:33:12 -07:00
|
|
|
using namespace frc;
|
|
|
|
|
|
2017-10-11 23:27:49 -04:00
|
|
|
static const std::string kName = ".name";
|
2015-06-30 15:01:20 -04:00
|
|
|
static const std::string kRunning = "running";
|
2017-10-11 23:27:49 -04:00
|
|
|
static const std::string kIsParented = ".isParented";
|
2013-12-15 18:30:16 -05:00
|
|
|
|
|
|
|
|
int Command::m_commandCounter = 0;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Creates a new command.
|
2017-11-16 00:33:51 -08:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* The name of this command will be default.
|
|
|
|
|
*/
|
2015-07-09 01:27:56 -07:00
|
|
|
Command::Command() : Command("", -1.0) {}
|
2013-12-15 18:30:16 -05:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Creates a new command with the given name and no timeout.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* @param name the name for this command
|
|
|
|
|
*/
|
2016-05-20 17:30:37 -07:00
|
|
|
Command::Command(const std::string& name) : Command(name, -1.0) {}
|
2013-12-15 18:30:16 -05:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Creates a new command with the given timeout and a default name.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* @param timeout the time (in seconds) before this command "times out"
|
2017-11-16 00:33:51 -08:00
|
|
|
* @see IsTimedOut()
|
2013-12-15 18:30:16 -05:00
|
|
|
*/
|
2015-07-24 19:19:40 -04:00
|
|
|
Command::Command(double timeout) : Command("", timeout) {}
|
2013-12-15 18:30:16 -05:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Creates a new command with the given name and timeout.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
|
|
|
|
* @param name the name of the command
|
2013-12-15 18:30:16 -05:00
|
|
|
* @param timeout the time (in seconds) before this command "times out"
|
2017-11-16 00:33:51 -08:00
|
|
|
* @see IsTimedOut()
|
2013-12-15 18:30:16 -05:00
|
|
|
*/
|
2016-05-20 17:30:37 -07:00
|
|
|
Command::Command(const std::string& name, double timeout) {
|
2015-07-24 19:19:40 -04:00
|
|
|
// We use -1.0 to indicate no timeout.
|
|
|
|
|
if (timeout < 0.0 && timeout != -1.0)
|
2015-06-25 15:07:55 -04:00
|
|
|
wpi_setWPIErrorWithContext(ParameterOutOfRange, "timeout < 0.0");
|
2015-06-29 02:43:44 -07:00
|
|
|
|
|
|
|
|
m_timeout = timeout;
|
2015-07-09 01:27:56 -07:00
|
|
|
|
|
|
|
|
// If name contains an empty string
|
|
|
|
|
if (name.length() == 0) {
|
|
|
|
|
m_name = std::string("Command_") + std::string(typeid(*this).name());
|
2016-05-20 17:30:37 -07:00
|
|
|
} else {
|
2015-07-09 01:27:56 -07:00
|
|
|
m_name = name;
|
|
|
|
|
}
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
2015-08-13 23:17:19 -07:00
|
|
|
Command::~Command() {
|
2017-09-02 00:17:43 -07:00
|
|
|
if (m_runningListener != 0) m_runningEntry.RemoveListener(m_runningListener);
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2016-05-20 17:30:37 -07:00
|
|
|
* Get the ID (sequence number) for this command.
|
|
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* The ID is a unique sequence number that is incremented for each command.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2017-11-16 00:33:51 -08:00
|
|
|
* @return The ID of this command
|
2013-12-15 18:30:16 -05:00
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
int Command::GetID() const { return m_commandID; }
|
2013-12-15 18:30:16 -05:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sets the timeout of this command.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* @param timeout the timeout (in seconds)
|
2017-11-16 00:33:51 -08:00
|
|
|
* @see IsTimedOut()
|
2013-12-15 18:30:16 -05:00
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
void Command::SetTimeout(double timeout) {
|
|
|
|
|
if (timeout < 0.0)
|
|
|
|
|
wpi_setWPIErrorWithContext(ParameterOutOfRange, "timeout < 0.0");
|
|
|
|
|
else
|
|
|
|
|
m_timeout = timeout;
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns the time since this command was initialized (in seconds).
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* This function will work even if there is no specified timeout.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* @return the time since this command was initialized (in seconds).
|
|
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
double Command::TimeSinceInitialized() const {
|
|
|
|
|
if (m_startTime < 0.0)
|
|
|
|
|
return 0.0;
|
|
|
|
|
else
|
|
|
|
|
return Timer::GetFPGATimestamp() - m_startTime;
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2017-11-16 00:33:51 -08:00
|
|
|
* This method specifies that the given Subsystem is used by this command.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* This method is crucial to the functioning of the Command System in general.
|
|
|
|
|
*
|
2017-11-16 00:33:51 -08:00
|
|
|
* Note that the recommended way to call this method is in the constructor.
|
2013-12-15 18:30:16 -05:00
|
|
|
*
|
2017-11-16 00:33:51 -08:00
|
|
|
* @param subsystem The Subsystem required
|
2013-12-15 18:30:16 -05:00
|
|
|
* @see Subsystem
|
|
|
|
|
*/
|
2016-05-20 17:30:37 -07:00
|
|
|
void Command::Requires(Subsystem* subsystem) {
|
2015-06-25 15:07:55 -04:00
|
|
|
if (!AssertUnlocked("Can not add new requirement to command")) return;
|
|
|
|
|
|
2015-06-23 04:49:51 -07:00
|
|
|
if (subsystem != nullptr)
|
2015-06-25 15:07:55 -04:00
|
|
|
m_requirements.insert(subsystem);
|
|
|
|
|
else
|
|
|
|
|
wpi_setWPIErrorWithContext(NullParameter, "subsystem");
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Called when the command has been removed.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2017-11-16 00:33:51 -08:00
|
|
|
* This will call Interrupted() or End().
|
2013-12-15 18:30:16 -05:00
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
void Command::Removed() {
|
|
|
|
|
if (m_initialized) {
|
|
|
|
|
if (IsCanceled()) {
|
|
|
|
|
Interrupted();
|
|
|
|
|
_Interrupted();
|
|
|
|
|
} else {
|
|
|
|
|
End();
|
|
|
|
|
_End();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
m_initialized = false;
|
|
|
|
|
m_canceled = false;
|
|
|
|
|
m_running = false;
|
2017-09-02 00:17:43 -07:00
|
|
|
if (m_runningEntry) m_runningEntry.SetBoolean(false);
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2017-11-16 00:33:51 -08:00
|
|
|
* Starts up the command. Gets the command ready to start.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2017-11-16 00:33:51 -08:00
|
|
|
* 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.
|
2013-12-15 18:30:16 -05:00
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
void Command::Start() {
|
|
|
|
|
LockChanges();
|
2015-06-23 04:49:51 -07:00
|
|
|
if (m_parent != nullptr)
|
2015-06-25 15:07:55 -04:00
|
|
|
wpi_setWPIErrorWithContext(
|
|
|
|
|
CommandIllegalUse,
|
|
|
|
|
"Can not start a command that is part of a command group");
|
2013-12-15 18:30:16 -05:00
|
|
|
|
Revert changes preventing old user code from compiling.
I'm not 100% sure whether we want these, but they are a quick
find and replace to do.
Basically, there are two primary things that we have done
this summer that break existing user code:
-Changing GetInstance() calls to return references instead
of pointers. This forces users to change from doing something
like LiveWindow::GetInstance()->AddSensor() to LiveWindow::GetInstance().AddSensor().
-Making PIDGet() and related calls const, forcing users to change
the function signatures wherever they override them.
The GetInstance() calls don't really matter to me either way,
especially since there are no real ownership issues going on there,
unlike the rest of the smart pointer-related changes.
For the const stuff, it is certainly more correct to mandate that
user PIDGet() functions be const and the such, but at the same time,
I'm not sure that there is any strong need for it, and the errors
generated are not the most helpful. While this wouldn't necessarily
be an issue for more experienced teams or completely new teams (who
don't have any old code to be reusing), it may cause issues for more
average teams who aren't familiar with the intricacies of C++ anything.
Change-Id: I6e7007982069292ea70e6d0fc8ca40203340df1b
2015-07-24 19:19:40 -04:00
|
|
|
Scheduler::GetInstance()->AddCommand(this);
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The run method is used internally to actually run the commands.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2017-11-16 00:33:51 -08:00
|
|
|
* @return Whether or not the command should stay within the Scheduler.
|
2013-12-15 18:30:16 -05:00
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
bool Command::Run() {
|
2015-06-23 04:49:51 -07:00
|
|
|
if (!m_runWhenDisabled && m_parent == nullptr && RobotState::IsDisabled())
|
2015-06-25 15:07:55 -04:00
|
|
|
Cancel();
|
2013-12-15 18:30:16 -05:00
|
|
|
|
2015-06-25 15:07:55 -04:00
|
|
|
if (IsCanceled()) return false;
|
2013-12-15 18:30:16 -05:00
|
|
|
|
2015-06-25 15:07:55 -04:00
|
|
|
if (!m_initialized) {
|
|
|
|
|
m_initialized = true;
|
|
|
|
|
StartTiming();
|
|
|
|
|
_Initialize();
|
|
|
|
|
Initialize();
|
|
|
|
|
}
|
|
|
|
|
_Execute();
|
|
|
|
|
Execute();
|
|
|
|
|
return !IsFinished();
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
2016-11-18 17:42:40 -05:00
|
|
|
/**
|
|
|
|
|
* The initialize method is called the first time this Command is run after
|
|
|
|
|
* being started.
|
|
|
|
|
*/
|
|
|
|
|
void Command::Initialize() {}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The execute method is called repeatedly until this Command either finishes
|
|
|
|
|
* or is canceled.
|
|
|
|
|
*/
|
|
|
|
|
void Command::Execute() {}
|
|
|
|
|
|
|
|
|
|
/**
|
2017-11-16 00:33:51 -08:00
|
|
|
* 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.
|
2016-11-18 17:42:40 -05:00
|
|
|
*/
|
|
|
|
|
void Command::End() {}
|
|
|
|
|
|
|
|
|
|
/**
|
2017-11-16 00:33:51 -08:00
|
|
|
* Called when the command ends because somebody called Cancel() or another
|
|
|
|
|
* command shared the same requirements as this one, and booted it out.
|
2016-11-18 17:42:40 -05:00
|
|
|
*
|
2017-11-16 00:33:51 -08:00
|
|
|
* This is where you may want to wrap up loose ends, like shutting off a motor
|
|
|
|
|
* that was being used in the command.
|
2016-11-18 17:42:40 -05:00
|
|
|
*
|
2017-11-16 00:33:51 -08:00
|
|
|
* Generally, it is useful to simply call the End() method within this method,
|
|
|
|
|
* as done here.
|
2016-11-18 17:42:40 -05:00
|
|
|
*/
|
|
|
|
|
void Command::Interrupted() { End(); }
|
|
|
|
|
|
2015-06-25 15:07:55 -04:00
|
|
|
void Command::_Initialize() {}
|
2013-12-15 18:30:16 -05:00
|
|
|
|
2015-06-25 15:07:55 -04:00
|
|
|
void Command::_Interrupted() {}
|
|
|
|
|
|
|
|
|
|
void Command::_Execute() {}
|
|
|
|
|
|
|
|
|
|
void Command::_End() {}
|
2013-12-15 18:30:16 -05:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Called to indicate that the timer should start.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2017-11-16 00:33:51 -08:00
|
|
|
* This is called right before Initialize() is, inside the Run() method.
|
2013-12-15 18:30:16 -05:00
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
void Command::StartTiming() { m_startTime = Timer::GetFPGATimestamp(); }
|
2013-12-15 18:30:16 -05:00
|
|
|
|
|
|
|
|
/**
|
2017-11-16 00:33:51 -08:00
|
|
|
* Returns whether or not the TimeSinceInitialized() method returns a number
|
|
|
|
|
* which is greater than or equal to the timeout for the command.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* If there is no timeout, this will always return false.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* @return whether the time has expired
|
|
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
bool Command::IsTimedOut() const {
|
|
|
|
|
return m_timeout != -1 && TimeSinceInitialized() >= m_timeout;
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2017-11-16 00:33:51 -08:00
|
|
|
* Returns the requirements (as an std::set of Subsystem pointers) of this
|
|
|
|
|
* command.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2017-11-16 00:33:51 -08:00
|
|
|
* @return The requirements (as an std::set of Subsystem pointers) of this
|
|
|
|
|
* command
|
2013-12-15 18:30:16 -05:00
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
Command::SubsystemSet Command::GetRequirements() const {
|
|
|
|
|
return m_requirements;
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2016-05-20 17:30:37 -07:00
|
|
|
* Prevents further changes from being made.
|
2013-12-15 18:30:16 -05:00
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
void Command::LockChanges() { m_locked = true; }
|
2013-12-15 18:30:16 -05:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* If changes are locked, then this will generate a CommandIllegalUse error.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2017-11-16 00:33:51 -08:00
|
|
|
* @param message The message to report on error (it is appended by a default
|
2016-05-20 17:30:37 -07:00
|
|
|
* message)
|
2017-11-16 00:33:51 -08:00
|
|
|
* @return True if assert passed, false if assert failed.
|
2013-12-15 18:30:16 -05:00
|
|
|
*/
|
2016-05-20 17:30:37 -07:00
|
|
|
bool Command::AssertUnlocked(const std::string& message) {
|
2015-06-25 15:07:55 -04:00
|
|
|
if (m_locked) {
|
2016-05-20 17:30:37 -07:00
|
|
|
std::string buf =
|
|
|
|
|
message + " after being started or being added to a command group";
|
2015-06-25 15:07:55 -04:00
|
|
|
wpi_setWPIErrorWithContext(CommandIllegalUse, buf);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2017-11-16 00:33:51 -08:00
|
|
|
* Sets the parent of this command. No actual change is made to the group.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* @param parent the parent
|
|
|
|
|
*/
|
2016-05-20 17:30:37 -07:00
|
|
|
void Command::SetParent(CommandGroup* parent) {
|
2015-06-23 04:49:51 -07:00
|
|
|
if (parent == nullptr) {
|
2015-06-25 15:07:55 -04:00
|
|
|
wpi_setWPIErrorWithContext(NullParameter, "parent");
|
2015-06-23 04:49:51 -07:00
|
|
|
} else if (m_parent != nullptr) {
|
2015-06-25 15:07:55 -04:00
|
|
|
wpi_setWPIErrorWithContext(CommandIllegalUse,
|
|
|
|
|
"Can not give command to a command group after "
|
|
|
|
|
"already being put in a command group");
|
|
|
|
|
} else {
|
|
|
|
|
LockChanges();
|
|
|
|
|
m_parent = parent;
|
2017-09-02 00:17:43 -07:00
|
|
|
if (m_isParentedEntry) m_isParentedEntry.SetBoolean(true);
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
2017-01-04 23:48:13 -08:00
|
|
|
/**
|
2017-11-16 00:33:51 -08:00
|
|
|
* Clears list of subsystem requirements.
|
|
|
|
|
*
|
|
|
|
|
* This is only used by ConditionalCommand so cancelling the chosen command
|
|
|
|
|
* works properly in CommandGroup.
|
2017-01-04 23:48:13 -08:00
|
|
|
*/
|
|
|
|
|
void Command::ClearRequirements() { m_requirements.clear(); }
|
|
|
|
|
|
2013-12-15 18:30:16 -05:00
|
|
|
/**
|
|
|
|
|
* This is used internally to mark that the command has been started.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* The lifecycle of a command is:
|
|
|
|
|
*
|
2017-11-16 00:33:51 -08:00
|
|
|
* StartRunning() is called. Run() is called (multiple times potentially).
|
|
|
|
|
* Removed() is called.
|
2013-12-15 18:30:16 -05:00
|
|
|
*
|
2017-11-16 00:33:51 -08:00
|
|
|
* It is very important that StartRunning() and Removed() be called in order or
|
|
|
|
|
* some assumptions of the code will be broken.
|
2013-12-15 18:30:16 -05:00
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
void Command::StartRunning() {
|
|
|
|
|
m_running = true;
|
|
|
|
|
m_startTime = -1;
|
2017-09-02 00:17:43 -07:00
|
|
|
if (m_runningEntry) m_runningEntry.SetBoolean(true);
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns whether or not the command is running.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* This may return true even if the command has just been canceled, as it may
|
2017-11-16 00:33:51 -08:00
|
|
|
* not have yet called Interrupted().
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* @return whether or not the command is running
|
|
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
bool Command::IsRunning() const { return m_running; }
|
2013-12-15 18:30:16 -05:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This will cancel the current command.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2017-11-16 00:33:51 -08:00
|
|
|
* 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.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2017-11-16 00:33:51 -08:00
|
|
|
* A command can not be canceled if it is a part of a command group, you must
|
|
|
|
|
* cancel the command group instead.
|
2013-12-15 18:30:16 -05:00
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
void Command::Cancel() {
|
2015-06-23 04:49:51 -07:00
|
|
|
if (m_parent != nullptr)
|
2015-06-25 15:07:55 -04:00
|
|
|
wpi_setWPIErrorWithContext(
|
|
|
|
|
CommandIllegalUse,
|
|
|
|
|
"Can not cancel a command that is part of a command group");
|
2013-12-15 18:30:16 -05:00
|
|
|
|
2015-06-25 15:07:55 -04:00
|
|
|
_Cancel();
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2017-11-16 00:33:51 -08:00
|
|
|
* This works like Cancel(), except that it doesn't throw an exception if it is
|
2016-05-20 17:30:37 -07:00
|
|
|
* a part of a command group.
|
|
|
|
|
*
|
|
|
|
|
* Should only be called by the parent command group.
|
2013-12-15 18:30:16 -05:00
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
void Command::_Cancel() {
|
|
|
|
|
if (IsRunning()) m_canceled = true;
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns whether or not this has been canceled.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* @return whether or not this has been canceled
|
|
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
bool Command::IsCanceled() const { return m_canceled; }
|
2013-12-15 18:30:16 -05:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns whether or not this command can be interrupted.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* @return whether or not this command can be interrupted
|
|
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
bool Command::IsInterruptible() const { return m_interruptible; }
|
2013-12-15 18:30:16 -05:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sets whether or not this command can be interrupted.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* @param interruptible whether or not this command can be interrupted
|
|
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
void Command::SetInterruptible(bool interruptible) {
|
|
|
|
|
m_interruptible = interruptible;
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2017-11-16 00:33:51 -08:00
|
|
|
* Checks if the command requires the given Subsystem.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* @param system the system
|
2015-06-23 04:49:51 -07:00
|
|
|
* @return whether or not the subsystem is required (false if given nullptr)
|
2013-12-15 18:30:16 -05:00
|
|
|
*/
|
2016-05-20 17:30:37 -07:00
|
|
|
bool Command::DoesRequire(Subsystem* system) const {
|
2015-06-25 15:07:55 -04:00
|
|
|
return m_requirements.count(system) > 0;
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2017-11-16 00:33:51 -08:00
|
|
|
* Returns the CommandGroup that this command is a part of.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2017-11-16 00:33:51 -08:00
|
|
|
* Will return null if this Command is not in a group.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2017-11-16 00:33:51 -08:00
|
|
|
* @return The CommandGroup that this command is a part of (or null if not in
|
|
|
|
|
* group)
|
2013-12-15 18:30:16 -05:00
|
|
|
*/
|
2016-05-20 17:30:37 -07:00
|
|
|
CommandGroup* Command::GetGroup() const { return m_parent; }
|
2013-12-15 18:30:16 -05:00
|
|
|
|
|
|
|
|
/**
|
2017-11-16 00:33:51 -08:00
|
|
|
* Sets whether or not this Command should run when the robot is disabled.
|
2013-12-15 18:30:16 -05:00
|
|
|
*
|
2017-11-16 00:33:51 -08:00
|
|
|
* By default a command will not run when the robot is disabled, and will in
|
|
|
|
|
* fact be canceled.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2017-11-16 00:33:51 -08:00
|
|
|
* @param run Whether this command should run when the robot is disabled.
|
2013-12-15 18:30:16 -05:00
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
void Command::SetRunWhenDisabled(bool run) { m_runWhenDisabled = run; }
|
2013-12-15 18:30:16 -05:00
|
|
|
|
|
|
|
|
/**
|
2017-11-16 00:33:51 -08:00
|
|
|
* Returns whether or not this Command will run when the robot is disabled, or
|
|
|
|
|
* if it will cancel itself.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2017-11-16 00:33:51 -08:00
|
|
|
* @return Whether this Command will run when the robot is disabled, or if it
|
|
|
|
|
* will cancel itself.
|
2013-12-15 18:30:16 -05:00
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
bool Command::WillRunWhenDisabled() const { return m_runWhenDisabled; }
|
2013-12-15 18:30:16 -05:00
|
|
|
|
2016-05-20 17:30:37 -07:00
|
|
|
std::string Command::GetName() const { return m_name; }
|
2013-12-15 18:30:16 -05:00
|
|
|
|
2015-06-25 15:07:55 -04:00
|
|
|
std::string Command::GetSmartDashboardType() const { return "Command"; }
|
2013-12-15 18:30:16 -05:00
|
|
|
|
2017-09-02 00:17:43 -07:00
|
|
|
void Command::InitTable(std::shared_ptr<nt::NetworkTable> subtable) {
|
|
|
|
|
if (m_runningListener != 0) m_runningEntry.RemoveListener(m_runningListener);
|
2017-09-02 00:35:30 -07:00
|
|
|
if (subtable) {
|
|
|
|
|
subtable->GetEntry(kName).SetString(GetName());
|
|
|
|
|
m_runningEntry = subtable->GetEntry(kRunning);
|
2017-09-02 00:17:43 -07:00
|
|
|
m_runningEntry.SetBoolean(IsRunning());
|
2017-09-02 00:35:30 -07:00
|
|
|
m_isParentedEntry = subtable->GetEntry(kIsParented);
|
2017-09-02 00:17:43 -07:00
|
|
|
m_isParentedEntry.SetBoolean(m_parent != nullptr);
|
|
|
|
|
|
|
|
|
|
m_runningListener = m_runningEntry.AddListener(
|
|
|
|
|
[=](const nt::EntryNotification& event) {
|
|
|
|
|
if (!event.value->IsBoolean()) return;
|
|
|
|
|
if (event.value->GetBoolean()) {
|
|
|
|
|
if (!IsRunning()) Start();
|
|
|
|
|
} else {
|
|
|
|
|
if (IsRunning()) Cancel();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|