blob: 7e3ef611ba324ec2f5617cb7496bc12de7c3689c [file] [log] [blame]
Brian Silverman26e4e522015-12-17 01:56:40 -05001/*----------------------------------------------------------------------------*/
Brian Silverman1a675112016-02-20 20:42:49 -05002/* Copyright (c) FIRST 2011-2016. All Rights Reserved. */
Brian Silverman26e4e522015-12-17 01:56:40 -05003/* Open Source Software - may be modified and shared by FRC teams. The code */
Brian Silverman1a675112016-02-20 20:42:49 -05004/* must be accompanied by the FIRST BSD license file in the root directory of */
5/* the project. */
Brian Silverman26e4e522015-12-17 01:56:40 -05006/*----------------------------------------------------------------------------*/
7
8#include "Commands/Subsystem.h"
9
10#include "Commands/Command.h"
11#include "Commands/Scheduler.h"
12#include "WPIErrors.h"
13
14/**
15 * Creates a subsystem with the given name
16 * @param name the name of the subsystem
17 */
18Subsystem::Subsystem(const std::string &name) {
19 m_name = name;
20 Scheduler::GetInstance()->RegisterSubsystem(this);
21}
22/**
23 * Initialize the default command for this subsystem
24 * This is meant to be the place to call SetDefaultCommand in a subsystem and
25 * will be called
26 * on all the subsystems by the CommandBase method before the program starts
27 * running by using
28 * the list of all registered Subsystems inside the Scheduler.
29 *
30 * This should be overridden by a Subsystem that has a default Command
31 */
32void Subsystem::InitDefaultCommand() {}
33
34/**
35 * Sets the default command. If this is not called or is called with null,
36 * then there will be no default command for the subsystem.
37 *
38 * <p><b>WARNING:</b> This should <b>NOT</b> be called in a constructor if the
39 * subsystem is a
40 * singleton.</p>
41 *
42 * @param command the default command (or null if there should be none)
43 */
44void Subsystem::SetDefaultCommand(Command *command) {
45 if (command == nullptr) {
46 m_defaultCommand = nullptr;
47 } else {
48 bool found = false;
49 Command::SubsystemSet requirements = command->GetRequirements();
50 auto iter = requirements.begin();
51 for (; iter != requirements.end(); iter++) {
52 if (*iter == this) {
53 found = true;
54 break;
55 }
56 }
57
58 if (!found) {
59 wpi_setWPIErrorWithContext(
60 CommandIllegalUse, "A default command must require the subsystem");
61 return;
62 }
63
64 m_defaultCommand = command;
65 }
66 if (m_table != nullptr) {
67 if (m_defaultCommand != nullptr) {
68 m_table->PutBoolean("hasDefault", true);
69 m_table->PutString("default", m_defaultCommand->GetName());
70 } else {
71 m_table->PutBoolean("hasDefault", false);
72 }
73 }
74}
75
76/**
77 * Returns the default command (or null if there is none).
78 * @return the default command
79 */
80Command *Subsystem::GetDefaultCommand() {
81 if (!m_initializedDefaultCommand) {
82 m_initializedDefaultCommand = true;
83 InitDefaultCommand();
84 }
85 return m_defaultCommand;
86}
87
88/**
89 * Sets the current command
90 * @param command the new current command
91 */
92void Subsystem::SetCurrentCommand(Command *command) {
93 m_currentCommand = command;
94 m_currentCommandChanged = true;
95}
96
97/**
98 * Returns the command which currently claims this subsystem.
99 * @return the command which currently claims this subsystem
100 */
101Command *Subsystem::GetCurrentCommand() const { return m_currentCommand; }
102
103/**
104 * Call this to alert Subsystem that the current command is actually the
105 * command.
106 * Sometimes, the {@link Subsystem} is told that it has no command while the
107 * {@link Scheduler}
108 * is going through the loop, only to be soon after given a new one. This will
109 * avoid that situation.
110 */
111void Subsystem::ConfirmCommand() {
112 if (m_currentCommandChanged) {
113 if (m_table != nullptr) {
114 if (m_currentCommand != nullptr) {
115 m_table->PutBoolean("hasCommand", true);
116 m_table->PutString("command", m_currentCommand->GetName());
117 } else {
118 m_table->PutBoolean("hasCommand", false);
119 }
120 }
121 m_currentCommandChanged = false;
122 }
123}
124
125std::string Subsystem::GetName() const { return m_name; }
126
127std::string Subsystem::GetSmartDashboardType() const { return "Subsystem"; }
128
129void Subsystem::InitTable(std::shared_ptr<ITable> table) {
130 m_table = table;
131 if (m_table != nullptr) {
132 if (m_defaultCommand != nullptr) {
133 m_table->PutBoolean("hasDefault", true);
134 m_table->PutString("default", m_defaultCommand->GetName());
135 } else {
136 m_table->PutBoolean("hasDefault", false);
137 }
138 if (m_currentCommand != nullptr) {
139 m_table->PutBoolean("hasCommand", true);
140 m_table->PutString("command", m_currentCommand->GetName());
141 } else {
142 m_table->PutBoolean("hasCommand", false);
143 }
144 }
145}
146
147std::shared_ptr<ITable> Subsystem::GetTable() const { return m_table; }