blob: 760c8f55759e5f2e3db9a767d9f5d7146555077d [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();
68
69
70protected:
71 void SetTimeout(double timeout);
72 bool IsTimedOut();
73 bool AssertUnlocked(const char *message);
74 void SetParent(CommandGroup *parent);
75 /**
76 * The initialize method is called the first time this Command is run after
77 * being started.
78 */
79 virtual void Initialize() = 0;
80 /**
81 * The execute method is called repeatedly until this Command either finishes
82 * or is canceled.
83 */
84 virtual void Execute() = 0;
85 /**
86 * Returns whether this command is finished.
87 * If it is, then the command will be removed
88 * and {@link Command#end() end()} will be called.
89 *
90 * <p>It may be useful for a team to reference the {@link Command#isTimedOut() isTimedOut()} method
91 * for time-sensitive commands.</p>
92 * @return whether this command is finished.
93 * @see Command#isTimedOut() isTimedOut()
94 */
95 virtual bool IsFinished() = 0;
96 /**
97 * Called when the command ended peacefully. This is where you may want
98 * to wrap up loose ends, like shutting off a motor that was being used
99 * in the command.
100 */
101 virtual void End() = 0;
102 /**
103 * Called when the command ends because somebody called {@link Command#cancel() cancel()}
104 * or another command shared the same requirements as this one, and booted
105 * it out.
106 *
107 * <p>This is where you may want
108 * to wrap up loose ends, like shutting off a motor that was being used
109 * in the command.</p>
110 *
111 * <p>Generally, it is useful to simply call the {@link Command#end() end()} method
112 * within this method</p>
113 */
114 virtual void Interrupted() = 0;
115 virtual void _Initialize();
116 virtual void _Interrupted();
117 virtual void _Execute();
118 virtual void _End();
119 virtual void _Cancel();
120
121private:
122 void InitCommand(const char *name, double timeout);
123 void LockChanges();
124 /*synchronized*/ void Removed();
125 void StartRunning();
126 void StartTiming();
127
128 /** The name of this command */
129 std::string m_name;
130 /** The time since this command was initialized */
131 double m_startTime;
132 /** The time (in seconds) before this command "times out" (or -1 if no timeout) */
133 double m_timeout;
134 /** Whether or not this command has been initialized */
135 bool m_initialized;
136 /** The requirements (or null if no requirements) */
137 SubsystemSet m_requirements;
138 /** Whether or not it is running */
139 bool m_running;
140 /** Whether or not it is interruptible*/
141 bool m_interruptible;
142 /** Whether or not it has been canceled */
143 bool m_canceled;
144 /** Whether or not it has been locked */
145 bool m_locked;
146 /** Whether this command should run when the robot is disabled */
147 bool m_runWhenDisabled;
148 /** The {@link CommandGroup} this is in */
149 CommandGroup *m_parent;
150
151
152public:
153 virtual std::string GetName();
154 virtual void InitTable(ITable* table);
155 virtual ITable* GetTable();
156 virtual std::string GetSmartDashboardType();
157 virtual void ValueChanged(ITable* source, const std::string& key, EntryValue value, bool isNew);
158protected:
159 ITable* m_table;
160};
161
162#endif