jerrym | f157933 | 2013-02-07 01:56:28 +0000 | [diff] [blame^] | 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 | #ifndef __COMMAND_H__
|
| 8 | #define __COMMAND_H__
|
| 9 |
|
| 10 | #include "ErrorBase.h"
|
| 11 | #include "SmartDashboard/NamedSendable.h"
|
| 12 | #include <set>
|
| 13 | #include <string>
|
| 14 |
|
| 15 | class CommandGroup;
|
| 16 | class 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 | */
|
| 43 | class Command : public ErrorBase, public NamedSendable, public ITableListener
|
| 44 | {
|
| 45 | friend class CommandGroup;
|
| 46 | friend class Scheduler;
|
| 47 | public:
|
| 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 |
|
| 70 | protected:
|
| 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 |
|
| 121 | private:
|
| 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 |
|
| 152 | public:
|
| 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);
|
| 158 | protected:
|
| 159 | ITable* m_table;
|
| 160 | };
|
| 161 |
|
| 162 | #endif
|