mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-19 00:41:43 +00:00
MacOS no longer ships 6.0, and Arch Linux's mesa GPU drivers are no longer compatible with LLVM 6.0.
266 lines
6.9 KiB
C++
266 lines
6.9 KiB
C++
/*----------------------------------------------------------------------------*/
|
|
/* Copyright (c) 2011-2020 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/commands/Command.h"
|
|
|
|
#include <typeinfo>
|
|
|
|
#include "frc/RobotState.h"
|
|
#include "frc/Timer.h"
|
|
#include "frc/WPIErrors.h"
|
|
#include "frc/commands/CommandGroup.h"
|
|
#include "frc/commands/Scheduler.h"
|
|
#include "frc/livewindow/LiveWindow.h"
|
|
#include "frc/smartdashboard/SendableBuilder.h"
|
|
#include "frc/smartdashboard/SendableRegistry.h"
|
|
|
|
using namespace frc;
|
|
|
|
int Command::m_commandCounter = 0;
|
|
|
|
Command::Command() : Command("", -1.0) {}
|
|
|
|
Command::Command(const wpi::Twine& name) : Command(name, -1.0) {}
|
|
|
|
Command::Command(double timeout) : Command("", timeout) {}
|
|
|
|
Command::Command(Subsystem& subsystem) : Command("", -1.0) {
|
|
Requires(&subsystem);
|
|
}
|
|
|
|
Command::Command(const wpi::Twine& name, double timeout) {
|
|
// We use -1.0 to indicate no timeout.
|
|
if (timeout < 0.0 && timeout != -1.0)
|
|
wpi_setWPIErrorWithContext(ParameterOutOfRange, "timeout < 0.0");
|
|
|
|
m_timeout = timeout;
|
|
|
|
// If name contains an empty string
|
|
if (name.isTriviallyEmpty() ||
|
|
(name.isSingleStringRef() && name.getSingleStringRef().empty())) {
|
|
SendableRegistry::GetInstance().Add(
|
|
this, "Command_" + wpi::Twine(typeid(*this).name()));
|
|
} else {
|
|
SendableRegistry::GetInstance().Add(this, name);
|
|
}
|
|
}
|
|
|
|
Command::Command(const wpi::Twine& name, Subsystem& subsystem)
|
|
: Command(name, -1.0) {
|
|
Requires(&subsystem);
|
|
}
|
|
|
|
Command::Command(double timeout, Subsystem& subsystem) : Command("", timeout) {
|
|
Requires(&subsystem);
|
|
}
|
|
|
|
Command::Command(const wpi::Twine& name, double timeout, Subsystem& subsystem)
|
|
: Command(name, timeout) {
|
|
Requires(&subsystem);
|
|
}
|
|
|
|
double Command::TimeSinceInitialized() const {
|
|
if (m_startTime < 0.0)
|
|
return 0.0;
|
|
else
|
|
return Timer::GetFPGATimestamp() - m_startTime;
|
|
}
|
|
|
|
void Command::Requires(Subsystem* subsystem) {
|
|
if (!AssertUnlocked("Can not add new requirement to command")) return;
|
|
|
|
if (subsystem != nullptr)
|
|
m_requirements.insert(subsystem);
|
|
else
|
|
wpi_setWPIErrorWithContext(NullParameter, "subsystem");
|
|
}
|
|
|
|
void Command::Start() {
|
|
LockChanges();
|
|
if (m_parent != nullptr)
|
|
wpi_setWPIErrorWithContext(
|
|
CommandIllegalUse,
|
|
"Can not start a command that is part of a command group");
|
|
|
|
m_completed = false;
|
|
Scheduler::GetInstance()->AddCommand(this);
|
|
}
|
|
|
|
bool Command::Run() {
|
|
if (!m_runWhenDisabled && m_parent == nullptr && RobotState::IsDisabled())
|
|
Cancel();
|
|
|
|
if (IsCanceled()) return false;
|
|
|
|
if (!m_initialized) {
|
|
m_initialized = true;
|
|
StartTiming();
|
|
_Initialize();
|
|
Initialize();
|
|
}
|
|
_Execute();
|
|
Execute();
|
|
return !IsFinished();
|
|
}
|
|
|
|
void Command::Cancel() {
|
|
if (m_parent != nullptr)
|
|
wpi_setWPIErrorWithContext(
|
|
CommandIllegalUse,
|
|
"Can not cancel a command that is part of a command group");
|
|
|
|
_Cancel();
|
|
}
|
|
|
|
bool Command::IsRunning() const { return m_running; }
|
|
|
|
bool Command::IsInitialized() const { return m_initialized; }
|
|
|
|
bool Command::IsCompleted() const { return m_completed; }
|
|
|
|
bool Command::IsCanceled() const { return m_canceled; }
|
|
|
|
bool Command::IsInterruptible() const { return m_interruptible; }
|
|
|
|
void Command::SetInterruptible(bool interruptible) {
|
|
m_interruptible = interruptible;
|
|
}
|
|
|
|
bool Command::DoesRequire(Subsystem* system) const {
|
|
return m_requirements.count(system) > 0;
|
|
}
|
|
|
|
const Command::SubsystemSet& Command::GetRequirements() const {
|
|
return m_requirements;
|
|
}
|
|
|
|
CommandGroup* Command::GetGroup() const { return m_parent; }
|
|
|
|
void Command::SetRunWhenDisabled(bool run) { m_runWhenDisabled = run; }
|
|
|
|
bool Command::WillRunWhenDisabled() const { return m_runWhenDisabled; }
|
|
|
|
int Command::GetID() const { return m_commandID; }
|
|
|
|
void Command::SetTimeout(double timeout) {
|
|
if (timeout < 0.0)
|
|
wpi_setWPIErrorWithContext(ParameterOutOfRange, "timeout < 0.0");
|
|
else
|
|
m_timeout = timeout;
|
|
}
|
|
|
|
bool Command::IsTimedOut() const {
|
|
return m_timeout != -1 && TimeSinceInitialized() >= m_timeout;
|
|
}
|
|
|
|
bool Command::AssertUnlocked(const std::string& message) {
|
|
if (m_locked) {
|
|
std::string buf =
|
|
message + " after being started or being added to a command group";
|
|
wpi_setWPIErrorWithContext(CommandIllegalUse, buf);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void Command::SetParent(CommandGroup* parent) {
|
|
if (parent == nullptr) {
|
|
wpi_setWPIErrorWithContext(NullParameter, "parent");
|
|
} else if (m_parent != nullptr) {
|
|
wpi_setWPIErrorWithContext(CommandIllegalUse,
|
|
"Can not give command to a command group after "
|
|
"already being put in a command group");
|
|
} else {
|
|
LockChanges();
|
|
m_parent = parent;
|
|
}
|
|
}
|
|
|
|
bool Command::IsParented() const { return m_parent != nullptr; }
|
|
|
|
void Command::ClearRequirements() { m_requirements.clear(); }
|
|
|
|
void Command::Initialize() {}
|
|
|
|
void Command::Execute() {}
|
|
|
|
void Command::End() {}
|
|
|
|
void Command::Interrupted() { End(); }
|
|
|
|
void Command::_Initialize() { m_completed = false; }
|
|
|
|
void Command::_Interrupted() { m_completed = true; }
|
|
|
|
void Command::_Execute() {}
|
|
|
|
void Command::_End() { m_completed = true; }
|
|
|
|
void Command::_Cancel() {
|
|
if (IsRunning()) m_canceled = true;
|
|
}
|
|
|
|
void Command::LockChanges() { m_locked = true; }
|
|
|
|
void Command::Removed() {
|
|
if (m_initialized) {
|
|
if (IsCanceled()) {
|
|
Interrupted();
|
|
_Interrupted();
|
|
} else {
|
|
End();
|
|
_End();
|
|
}
|
|
}
|
|
m_initialized = false;
|
|
m_canceled = false;
|
|
m_running = false;
|
|
m_completed = true;
|
|
}
|
|
|
|
void Command::StartRunning() {
|
|
m_running = true;
|
|
m_startTime = -1;
|
|
m_completed = false;
|
|
}
|
|
|
|
void Command::StartTiming() { m_startTime = Timer::GetFPGATimestamp(); }
|
|
|
|
std::string Command::GetName() const {
|
|
return SendableRegistry::GetInstance().GetName(this);
|
|
}
|
|
|
|
void Command::SetName(const wpi::Twine& name) {
|
|
SendableRegistry::GetInstance().SetName(this, name);
|
|
}
|
|
|
|
std::string Command::GetSubsystem() const {
|
|
return SendableRegistry::GetInstance().GetSubsystem(this);
|
|
}
|
|
|
|
void Command::SetSubsystem(const wpi::Twine& name) {
|
|
SendableRegistry::GetInstance().SetSubsystem(this, name);
|
|
}
|
|
|
|
void Command::InitSendable(SendableBuilder& builder) {
|
|
builder.SetSmartDashboardType("Command");
|
|
builder.AddStringProperty(
|
|
".name", [=]() { return SendableRegistry::GetInstance().GetName(this); },
|
|
nullptr);
|
|
builder.AddBooleanProperty(
|
|
"running", [=]() { return IsRunning(); },
|
|
[=](bool value) {
|
|
if (value) {
|
|
if (!IsRunning()) Start();
|
|
} else {
|
|
if (IsRunning()) Cancel();
|
|
}
|
|
});
|
|
builder.AddBooleanProperty(
|
|
".isParented", [=]() { return IsParented(); }, nullptr);
|
|
}
|