001 /*----------------------------------------------------------------------------*/ 002 /* Copyright (c) FIRST 2008-2012. All Rights Reserved. */ 003 /* Open Source Software - may be modified and shared by FRC teams. The code */ 004 /* must be accompanied by the FIRST BSD license file in the root directory of */ 005 /* the project. */ 006 /*----------------------------------------------------------------------------*/ 007 008 package edu.wpi.first.wpilibj.command; 009 010 import edu.wpi.first.wpilibj.NamedSendable; 011 import edu.wpi.first.wpilibj.tables.ITable; 012 import java.util.Enumeration; 013 import java.util.Vector; 014 015 /** 016 * This class defines a major component of the robot. 017 * 018 * <p>A good example of a subsystem is the driveline, or a claw if the robot has one.</p> 019 * 020 * <p>All motors should be a part of a subsystem. For instance, all the wheel motors should be 021 * a part of some kind of "Driveline" subsystem.</p> 022 * 023 * <p>Subsystems are used within the command system as requirements for {@link Command}. 024 * Only one command which requires a subsystem can run at a time. Also, subsystems 025 * can have default commands which are started if there is no command running which 026 * requires this subsystem.</p> 027 * 028 * @author Joe Grinstead 029 * @see Command 030 */ 031 public abstract class Subsystem implements NamedSendable{ 032 033 /** Whether or not getDefaultCommand() was called */ 034 private boolean initializedDefaultCommand = false; 035 /** The current command */ 036 private Command currentCommand; 037 private boolean currentCommandChanged; 038 039 /** The default command */ 040 private Command defaultCommand; 041 /** The name */ 042 private String name; 043 /** List of all subsystems created */ 044 private static Vector allSubsystems = new Vector(); 045 046 /** 047 * Creates a subsystem with the given name 048 * @param name the name of the subsystem 049 */ 050 public Subsystem(String name) { 051 this.name = name; 052 Scheduler.getInstance().registerSubsystem(this); 053 } 054 055 /** 056 * Creates a subsystem. This will set the name to the name of the class. 057 */ 058 public Subsystem() { 059 this.name = getClass().getName().substring(getClass().getName().lastIndexOf('.') + 1); 060 Scheduler.getInstance().registerSubsystem(this); 061 currentCommandChanged = true; 062 } 063 064 /** 065 * Initialize the default command for a subsystem 066 * By default subsystems have no default command, but if they do, the default command is set 067 * with this method. It is called on all Subsystems by CommandBase in the users program after 068 * all the Subsystems are created. 069 */ 070 protected abstract void initDefaultCommand(); 071 072 /** 073 * Sets the default command. If this is not called or is called with null, 074 * then there will be no default command for the subsystem. 075 * 076 * <p><b>WARNING:</b> This should <b>NOT</b> be called in a constructor if the subsystem is a 077 * singleton.</p> 078 * 079 * @param command the default command (or null if there should be none) 080 * @throws IllegalUseOfCommandException if the command does not require the subsystem 081 */ 082 protected void setDefaultCommand(Command command) { 083 if (command == null) { 084 defaultCommand = null; 085 } else { 086 boolean found = false; 087 Enumeration requirements = command.getRequirements(); 088 while (requirements.hasMoreElements()) { 089 if (requirements.nextElement().equals(this)) { 090 found = true; 091 // } else { 092 // throw new IllegalUseOfCommandException("A default command cannot require multiple subsystems"); 093 } 094 } 095 if (!found) { 096 throw new IllegalUseOfCommandException("A default command must require the subsystem"); 097 } 098 defaultCommand = command; 099 } 100 if (table != null) { 101 if (defaultCommand != null) { 102 table.putBoolean("hasDefault", true); 103 table.putString("default", defaultCommand.getName()); 104 } else { 105 table.putBoolean("hasDefault", false); 106 } 107 } 108 } 109 110 /** 111 * Returns the default command (or null if there is none). 112 * @return the default command 113 */ 114 protected Command getDefaultCommand() { 115 if (!initializedDefaultCommand) { 116 initializedDefaultCommand = true; 117 initDefaultCommand(); 118 } 119 return defaultCommand; 120 } 121 122 /** 123 * Sets the current command 124 * @param command the new current command 125 */ 126 void setCurrentCommand(Command command) { 127 currentCommand = command; 128 currentCommandChanged = true; 129 } 130 131 /** 132 * Call this to alert Subsystem that the current command is actually the command. 133 * Sometimes, the {@link Subsystem} is told that it has no command while the {@link Scheduler} 134 * is going through the loop, only to be soon after given a new one. This will avoid that situation. 135 */ 136 void confirmCommand() { 137 if (currentCommandChanged) { 138 if (table != null) { 139 if (currentCommand != null) { 140 table.putBoolean("hasCommand", true); 141 table.putString("command", currentCommand.getName()); 142 } else { 143 table.putBoolean("hasCommand", false); 144 } 145 } 146 currentCommandChanged = false; 147 } 148 } 149 150 /** 151 * Returns the command which currently claims this subsystem. 152 * @return the command which currently claims this subsystem 153 */ 154 public Command getCurrentCommand() { 155 return currentCommand; 156 } 157 158 public String toString() { 159 return getName(); 160 } 161 162 /** 163 * Returns the name of this subsystem, which is by default the class name. 164 * @return the name of this subsystem 165 */ 166 public String getName() { 167 return name; 168 } 169 170 public String getSmartDashboardType(){ 171 return "Subsystem"; 172 } 173 private ITable table; 174 public void initTable(ITable table){ 175 this.table = table; 176 if(table!=null){ 177 if (defaultCommand != null) { 178 table.putBoolean("hasDefault", true); 179 table.putString("default", defaultCommand.getName()); 180 } else { 181 table.putBoolean("hasDefault", false); 182 } 183 if (currentCommand != null) { 184 table.putBoolean("hasCommand", true); 185 table.putString("command", currentCommand.getName()); 186 } else { 187 table.putBoolean("hasCommand", false); 188 } 189 } 190 } 191 /** 192 * {@inheritDoc} 193 */ 194 public ITable getTable(){ 195 return table; 196 } 197 }