blob: 27046244445cb4ea836a8f9c3dab83d0fd4fa6b3 [file] [log] [blame]
jerrymf1579332013-02-07 01:56:28 +00001/*----------------------------------------------------------------------------*/
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#ifndef __COMMAND_H__
8#define __COMMAND_H__
9
10#include "ErrorBase.h"
11#include "SmartDashboard/NamedSendable.h"
12#include <set>
13#include <string>
14
15class CommandGroup;
16class Subsystem;
17
18/**
19 * The Command class is at the very core of the entire command framework.
20 * Every command can be started with a call to {@link Command#Start() Start()}.
21 * Once a command is started it will call {@link Command#Initialize() Initialize()}, and then
22 * will repeatedly call {@link Command#Execute() Execute()} until the {@link Command#IsFinished() IsFinished()}
23 * returns true. Once it does, {@link Command#End() End()} will be called.
24 *
25 * <p>However, if at any point while it is running {@link Command#Cancel() Cancel()} is called, then
26 * the command will be stopped and {@link Command#Interrupted() Interrupted()} will be called.</p>
27 *
28 * <p>If a command uses a {@link Subsystem}, then it should specify that it does so by
29 * calling the {@link Command#Requires(Subsystem) Requires(...)} method
30 * in its constructor. Note that a Command may have multiple requirements, and
31 * {@link Command#Requires(Subsystem) Requires(...)} should be
32 * called for each one.</p>
33 *
34 * <p>If a command is running and a new command with shared requirements is started,
35 * then one of two things will happen. If the active command is interruptible,
36 * then {@link Command#Cancel() Cancel()} will be called and the command will be removed
37 * to make way for the new one. If the active command is not interruptible, the
38 * other one will not even be started, and the active one will continue functioning.</p>
39 *
40 * @see CommandGroup
41 * @see Subsystem
42 */
43class Command : public ErrorBase, public NamedSendable, public ITableListener
44{
45 friend class CommandGroup;
46 friend class Scheduler;
47public:
48 Command();
49 Command(const char *name);
50 Command(double timeout);
51 Command(const char *name, double timeout);
52 virtual ~Command();
53 double TimeSinceInitialized();
54 void Requires(Subsystem *s);
55 bool IsCanceled();
56 void Start();
57 bool Run();
58 void Cancel();
59 bool IsRunning();
60 bool IsInterruptible();
61 void SetInterruptible(bool interruptible);
62 bool DoesRequire(Subsystem *subsystem);
63 typedef std::set<Subsystem *> SubsystemSet;
64 SubsystemSet GetRequirements();
65 CommandGroup *GetGroup();
66 void SetRunWhenDisabled(bool run);
67 bool WillRunWhenDisabled();
jerrym42dedc02013-02-25 01:59:14 +000068 int GetID();
jerrymf1579332013-02-07 01:56:28 +000069
70
71protected:
72 void SetTimeout(double timeout);
73 bool IsTimedOut();
74 bool AssertUnlocked(const char *message);
75 void SetParent(CommandGroup *parent);
76 /**
77 * The initialize method is called the first time this Command is run after
78 * being started.
79 */
80 virtual void Initialize() = 0;
81 /**
82 * The execute method is called repeatedly until this Command either finishes
83 * or is canceled.
84 */
85 virtual void Execute() = 0;
86 /**
87 * Returns whether this command is finished.
88 * If it is, then the command will be removed
89 * and {@link Command#end() end()} will be called.
90 *
91 * <p>It may be useful for a team to reference the {@link Command#isTimedOut() isTimedOut()} method
92 * for time-sensitive commands.</p>
93 * @return whether this command is finished.
94 * @see Command#isTimedOut() isTimedOut()
95 */
96 virtual bool IsFinished() = 0;
97 /**
98 * Called when the command ended peacefully. This is where you may want
99 * to wrap up loose ends, like shutting off a motor that was being used
100 * in the command.
101 */
102 virtual void End() = 0;
103 /**
104 * Called when the command ends because somebody called {@link Command#cancel() cancel()}
105 * or another command shared the same requirements as this one, and booted
106 * it out.
107 *
108 * <p>This is where you may want
109 * to wrap up loose ends, like shutting off a motor that was being used
110 * in the command.</p>
111 *
112 * <p>Generally, it is useful to simply call the {@link Command#end() end()} method
113 * within this method</p>
114 */
115 virtual void Interrupted() = 0;
116 virtual void _Initialize();
117 virtual void _Interrupted();
118 virtual void _Execute();
119 virtual void _End();
120 virtual void _Cancel();
121
122private:
123 void InitCommand(const char *name, double timeout);
124 void LockChanges();
125 /*synchronized*/ void Removed();
126 void StartRunning();
127 void StartTiming();
128
129 /** The name of this command */
130 std::string m_name;
131 /** The time since this command was initialized */
132 double m_startTime;
133 /** The time (in seconds) before this command "times out" (or -1 if no timeout) */
134 double m_timeout;
135 /** Whether or not this command has been initialized */
136 bool m_initialized;
137 /** The requirements (or null if no requirements) */
138 SubsystemSet m_requirements;
139 /** Whether or not it is running */
140 bool m_running;
141 /** Whether or not it is interruptible*/
142 bool m_interruptible;
143 /** Whether or not it has been canceled */
144 bool m_canceled;
145 /** Whether or not it has been locked */
146 bool m_locked;
147 /** Whether this command should run when the robot is disabled */
148 bool m_runWhenDisabled;
149 /** The {@link CommandGroup} this is in */
150 CommandGroup *m_parent;
jerrym42dedc02013-02-25 01:59:14 +0000151 int m_commandID;
152 static int m_commandCounter;
jerrymf1579332013-02-07 01:56:28 +0000153
154public:
155 virtual std::string GetName();
156 virtual void InitTable(ITable* table);
157 virtual ITable* GetTable();
158 virtual std::string GetSmartDashboardType();
159 virtual void ValueChanged(ITable* source, const std::string& key, EntryValue value, bool isNew);
160protected:
161 ITable* m_table;
162};
163
164#endif