Now you can download a copy of these docs so you can use them offline! Download now
Scheduler.cpp
1 /*----------------------------------------------------------------------------*/
2 /* Copyright (c) FIRST 2011. All Rights Reserved. */
3 /* Open Source Software - may be modified and shared by FRC teams. The code */
4 /* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */
5 /*----------------------------------------------------------------------------*/
6 
7 #include "Commands/Scheduler.h"
8 
9 #include "Buttons/ButtonScheduler.h"
10 #include "Commands/Subsystem.h"
11 #include "NetworkCommunication/UsageReporting.h"
12 #include "Synchronized.h"
13 #include "WPIErrors.h"
14 #include <iostream>
15 #include <set>
16 #include <semLib.h>
17 #include <algorithm>
18 
19 Scheduler *Scheduler::_instance = NULL;
20 
21 Scheduler::Scheduler() :
22  m_buttonsLock(NULL), m_additionsLock(NULL), m_adding(false) {
23  m_buttonsLock = semMCreate(
24  SEM_Q_PRIORITY | SEM_INVERSION_SAFE | SEM_DELETE_SAFE);
25  m_additionsLock = semMCreate(
26  SEM_Q_PRIORITY | SEM_INVERSION_SAFE | SEM_DELETE_SAFE);
27 
28  nUsageReporting::report(nUsageReporting::kResourceType_Command,
29  nUsageReporting::kCommand_Scheduler);
30 
31  m_table = NULL;
32  m_enabled = true;
33 }
34 
35 Scheduler::~Scheduler() {
36  semTake(m_additionsLock, WAIT_FOREVER);
37  semDelete(m_additionsLock);
38 
39  semTake(m_buttonsLock, WAIT_FOREVER);
40  semDelete(m_buttonsLock);
41 }
42 
48  if (_instance == NULL)
49  _instance = new Scheduler();
50  return _instance;
51 }
52 
53 void Scheduler::SetEnabled(bool enabled) {
54  m_enabled = enabled;
55 }
56 
64  Synchronized sync(m_additionsLock);
65  if (std::find(m_additions.begin(), m_additions.end(), command)
66  != m_additions.end())
67  return;
68  m_additions.push_back(command);
69 }
70 
71 void Scheduler::AddButton(ButtonScheduler *button) {
72  Synchronized sync(m_buttonsLock);
73  m_buttons.push_back(button);
74 }
75 
76 void Scheduler::ProcessCommandAddition(Command *command) {
77  if (command == NULL)
78  return;
79 
80  // Check to make sure no adding during adding
81  if (m_adding) {
82  wpi_setWPIErrorWithContext(IncompatibleState, "Can not start command from cancel method");
83  return;
84  }
85 
86  // Only add if not already in
87  CommandSet::iterator found = m_commands.find(command);
88  if (found == m_commands.end()) {
89  // Check that the requirements can be had
90  Command::SubsystemSet requirements = command->GetRequirements();
91  Command::SubsystemSet::iterator iter;
92  for (iter = requirements.begin(); iter != requirements.end(); iter++) {
93  Subsystem *lock = *iter;
94  if (lock->GetCurrentCommand() != NULL
95  && !lock->GetCurrentCommand()->IsInterruptible())
96  return;
97  }
98 
99  // Give it the requirements
100  m_adding = true;
101  for (iter = requirements.begin(); iter != requirements.end(); iter++) {
102  Subsystem *lock = *iter;
103  if (lock->GetCurrentCommand() != NULL) {
104  lock->GetCurrentCommand()->Cancel();
105  Remove(lock->GetCurrentCommand());
106  }
107  lock->SetCurrentCommand(command);
108  }
109  m_adding = false;
110 
111  m_commands.insert(command);
112 
113  command->StartRunning();
114  m_runningCommandsChanged = true;
115  }
116 }
117 
131  // Get button input (going backwards preserves button priority)
132  {
133  if (!m_enabled)
134  return;
135 
136  Synchronized sync(m_buttonsLock);
137  ButtonVector::reverse_iterator rButtonIter = m_buttons.rbegin();
138  for (; rButtonIter != m_buttons.rend(); rButtonIter++) {
139  (*rButtonIter)->Execute();
140  }
141  }
142 
143  m_runningCommandsChanged = false;
144 
145  // Loop through the commands
146  CommandSet::iterator commandIter = m_commands.begin();
147  for (; commandIter != m_commands.end();) {
148  Command *command = *commandIter;
149  // Increment before potentially removing to keep the iterator valid
150  commandIter++;
151  if (!command->Run()) {
152  Remove(command);
153  m_runningCommandsChanged = true;
154  }
155  }
156 
157  // Add the new things
158  {
159  Synchronized sync(m_additionsLock);
160  CommandVector::iterator additionsIter = m_additions.begin();
161  for (; additionsIter != m_additions.end(); additionsIter++) {
162  ProcessCommandAddition(*additionsIter);
163  }
164  m_additions.clear();
165  }
166 
167  // Add in the defaults
168  Command::SubsystemSet::iterator subsystemIter = m_subsystems.begin();
169  for (; subsystemIter != m_subsystems.end(); subsystemIter++) {
170  Subsystem *lock = *subsystemIter;
171  if (lock->GetCurrentCommand() == NULL) {
172  ProcessCommandAddition(lock->GetDefaultCommand());
173  }
174  lock->ConfirmCommand();
175  }
176 
177  UpdateTable();
178 }
179 
186  if (subsystem == NULL) {
187  wpi_setWPIErrorWithContext(NullParameter, "subsystem");
188  return;
189  }
190  m_subsystems.insert(subsystem);
191 }
192 
197 void Scheduler::Remove(Command *command) {
198  if (command == NULL) {
199  wpi_setWPIErrorWithContext(NullParameter, "command");
200  return;
201  }
202 
203  if (!m_commands.erase(command))
204  return;
205 
206  Command::SubsystemSet requirements = command->GetRequirements();
207  Command::SubsystemSet::iterator iter = requirements.begin();
208  for (; iter != requirements.end(); iter++) {
209  Subsystem *lock = *iter;
210  lock->SetCurrentCommand(NULL);
211  }
212 
213  command->Removed();
214 }
215 
216 void Scheduler::RemoveAll() {
217  while (m_commands.size() > 0) {
218  Remove(*m_commands.begin());
219  }
220 }
221 
226  CommandSet::iterator commandIter;
227  if (m_table != NULL) {
228  // Get the list of possible commands to cancel
229  m_table->RetrieveValue("Cancel", *toCancel);
230 // m_table->RetrieveValue("Ids", *ids);
231 
232  // cancel commands that have had the cancel buttons pressed
233  // on the SmartDashboad
234  if (toCancel->size() > 0) {
235  for (commandIter = m_commands.begin(); commandIter
236  != m_commands.end(); ++commandIter) {
237  for (unsigned i = 0; i < toCancel->size(); i++) {
238  Command *c = *commandIter;
239  if (c->GetID() == toCancel->get(i)) {
240  c->Cancel();
241  }
242  }
243  }
244  toCancel->setSize(0);
245  m_table->PutValue("Cancel", *toCancel);
246  }
247 
248  // Set the running commands
249  if (m_runningCommandsChanged) {
250  commands->setSize(0);
251  ids->setSize(0);
252  for (commandIter = m_commands.begin(); commandIter != m_commands.end(); ++commandIter) {
253  Command *c = *commandIter;
254  commands->add(c->GetName());
255  ids->add(c->GetID());
256  }
257  m_table->PutValue("Names", *commands);
258  m_table->PutValue("Ids", *ids);
259  }
260  }
261 }
262 
263 std::string Scheduler::GetName() {
264  return "Scheduler";
265 }
266 
267 std::string Scheduler::GetType() {
268  return "Scheduler";
269 }
270 
272  return "Scheduler";
273 }
274 
275 void Scheduler::InitTable(ITable *subTable) {
276  m_table = subTable;
277  commands = new StringArray();
278  ids = new NumberArray();
279  toCancel = new NumberArray();
280 
281  m_table->PutValue("Names", *commands);
282  m_table->PutValue("Ids", *ids);
283  m_table->PutValue("Cancel", *toCancel);
284 }
285 
287  return m_table;
288 }
std::string GetName()
Definition: Scheduler.cpp:263
bool IsInterruptible()
Definition: Command.cpp:384
Definition: ITable.h:26
void setSize(unsigned int size)
Definition: ArrayData.cpp:50
Command * GetCurrentCommand()
Definition: Subsystem.cpp:117
void Run()
Definition: Scheduler.cpp:130
void AddCommand(Command *command)
Definition: Scheduler.cpp:63
virtual std::string GetName()
Definition: Command.cpp:438
std::string GetSmartDashboardType()
Definition: Scheduler.cpp:271
void Cancel()
Definition: Command.cpp:353
Command * GetDefaultCommand()
Definition: Subsystem.cpp:94
void InitTable(ITable *subTable)
Definition: Scheduler.cpp:275
void UpdateTable()
Definition: Scheduler.cpp:225
int GetID()
Definition: Command.cpp:105
bool Run()
Definition: Command.cpp:199
void Remove(Command *command)
Definition: Scheduler.cpp:197
virtual void PutValue(std::string key, ComplexData &value)=0
void RegisterSubsystem(Subsystem *subsystem)
Definition: Scheduler.cpp:185
unsigned int size()
Definition: ArrayData.cpp:73
ITable * GetTable()
Definition: Scheduler.cpp:286
void SetCurrentCommand(Command *command)
Definition: Subsystem.cpp:107
static Scheduler * GetInstance()
Definition: Scheduler.cpp:47
SubsystemSet GetRequirements()
Definition: Command.cpp:260

Generated on Sat Apr 26 2014 12:26:45 for WPILibC++ by doxygen 1.8.6