001/* 002 * To change this template, choose Tools | Templates 003 * and open the template in the editor. 004 */ 005package edu.wpi.first.wpilibj.livewindow; 006 007import edu.wpi.first.wpilibj.command.Scheduler; 008import edu.wpi.first.wpilibj.networktables.NetworkTable; 009import edu.wpi.first.wpilibj.tables.ITable; 010import java.util.Enumeration; 011import java.util.Hashtable; 012import java.util.Vector; 013 014/** 015 * A LiveWindow component is a device (sensor or actuator) that should be added to the 016 * SmartDashboard in test mode. The components are cached until the first time the robot 017 * enters Test mode. This allows the components to be inserted, then renamed. 018 * @author brad 019 */ 020class LiveWindowComponent { 021 022 String m_subsystem; 023 String m_name; 024 boolean m_isSensor; 025 026 public LiveWindowComponent(String subsystem, String name, boolean isSensor) { 027 m_subsystem = subsystem; 028 m_name = name; 029 m_isSensor = isSensor; 030 } 031 032 public String getName() { 033 return m_name; 034 } 035 036 public String getSubsystem() { 037 return m_subsystem; 038 } 039 040 public boolean isSensor() { 041 return m_isSensor; 042 } 043} 044 045/** 046 * The LiveWindow class is the public interface for putting sensors and 047 * actuators on the LiveWindow. 048 * 049 * @author Alex Henning 050 */ 051public class LiveWindow { 052 053 private static Vector sensors = new Vector(); 054// private static Vector actuators = new Vector(); 055 private static Hashtable components = new Hashtable(); 056 private static ITable livewindowTable; 057 private static ITable statusTable; 058 private static boolean liveWindowEnabled = false; 059 private static boolean firstTime = true; 060 061 /** 062 * Initialize all the LiveWindow elements the first time we enter LiveWindow 063 * mode. By holding off creating the NetworkTable entries, it allows them to 064 * be redefined before the first time in LiveWindow mode. This allows 065 * default sensor and actuator values to be created that are replaced with 066 * the custom names from users calling addActuator and addSensor. 067 */ 068 private static void initializeLiveWindowComponents() { 069 System.out.println("Initializing the components first time"); 070 livewindowTable = NetworkTable.getTable("LiveWindow"); 071 statusTable = livewindowTable.getSubTable("~STATUS~"); 072 for (Enumeration e = components.keys(); e.hasMoreElements();) { 073 LiveWindowSendable component = (LiveWindowSendable) e.nextElement(); 074 LiveWindowComponent c = (LiveWindowComponent) components.get(component); 075 String subsystem = c.getSubsystem(); 076 String name = c.getName(); 077 System.out.println("Initializing table for '" + subsystem + "' '" + name + "'"); 078 livewindowTable.getSubTable(subsystem).putString("~TYPE~", "LW Subsystem"); 079 ITable table = livewindowTable.getSubTable(subsystem).getSubTable(name); 080 table.putString("~TYPE~", component.getSmartDashboardType()); 081 table.putString("Name", name); 082 table.putString("Subsystem", subsystem); 083 component.initTable(table); 084 if (c.isSensor()) { 085 sensors.addElement(component); 086 } 087 } 088 } 089 090 /** 091 * Set the enabled state of LiveWindow. If it's being enabled, turn off the 092 * scheduler and remove all the commands from the queue and enable all the 093 * components registered for LiveWindow. If it's being disabled, stop all 094 * the registered components and reenable the scheduler. TODO: add code to 095 * disable PID loops when enabling LiveWindow. The commands should reenable 096 * the PID loops themselves when they get rescheduled. This prevents arms 097 * from starting to move around, etc. after a period of adjusting them in 098 * LiveWindow mode. 099 */ 100 public static void setEnabled(boolean enabled) { 101 if (liveWindowEnabled != enabled) { 102 if (enabled) { 103 System.out.println("Starting live window mode."); 104 if (firstTime) { 105 initializeLiveWindowComponents(); 106 firstTime = false; 107 } 108 Scheduler.getInstance().disable(); 109 Scheduler.getInstance().removeAll(); 110 for (Enumeration e = components.keys(); e.hasMoreElements();) { 111 LiveWindowSendable component = (LiveWindowSendable) e.nextElement(); 112 component.startLiveWindowMode(); 113 } 114 } else { 115 System.out.println("stopping live window mode."); 116 for (Enumeration e = components.keys(); e.hasMoreElements();) { 117 LiveWindowSendable component = (LiveWindowSendable) e.nextElement(); 118 component.stopLiveWindowMode(); 119 } 120 Scheduler.getInstance().enable(); 121 } 122 liveWindowEnabled = enabled; 123 statusTable.putBoolean("LW Enabled", enabled); 124 } 125 } 126 127 /** 128 * The run method is called repeatedly to keep the values refreshed on the screen in 129 * test mode. 130 */ 131 public static void run() { 132 updateValues(); 133 } 134 135 /** 136 * Add a Sensor associated with the subsystem and with call it by the given 137 * name. 138 * 139 * @param subsystem The subsystem this component is part of. 140 * @param name The name of this component. 141 * @param component A LiveWindowSendable component that represents a sensor. 142 */ 143 public static void addSensor(String subsystem, String name, LiveWindowSendable component) { 144 components.put(component, new LiveWindowComponent(subsystem, name, true)); 145 } 146 147 /** 148 * Add an Actuator associated with the subsystem and with call it by the 149 * given name. 150 * 151 * @param subsystem The subsystem this component is part of. 152 * @param name The name of this component. 153 * @param component A LiveWindowSendable component that represents a 154 * actuator. 155 */ 156 public static void addActuator(String subsystem, String name, LiveWindowSendable component) { 157 components.put(component, new LiveWindowComponent(subsystem, name, false)); 158 } 159 160 /** 161 * Puts all sensor values on the live window. 162 */ 163 private static void updateValues() { 164 //TODO: gross - needs to be sped up 165 for (int i = 0; i < sensors.size(); i++) { 166 LiveWindowSendable lws = (LiveWindowSendable) sensors.elementAt(i); 167 lws.updateTable(); 168 } 169 // TODO: Add actuators? 170 // TODO: Add better rate limiting. 171 } 172 173 /** 174 * Add Sensor to LiveWindow. The components are shown with the type and 175 * channel like this: Gyro[1] for a gyro object connected to the first 176 * analog channel. 177 * 178 * @param moduleType A string indicating the type of the module used in the 179 * naming (above) 180 * @param channel The channel number the device is connected to 181 * @param component A reference to the object being added 182 */ 183 public static void addSensor(String moduleType, int channel, LiveWindowSendable component) { 184 addSensor("Ungrouped", moduleType + "[" + channel + "]", component); 185 if (sensors.contains(component)) { 186 sensors.removeElement(component); 187 } 188 sensors.addElement(component); 189 } 190 191 /** 192 * Add Actuator to LiveWindow. The components are shown with the module 193 * type, slot and channel like this: Servo[1,2] for a servo object connected 194 * to the first digital module and PWM port 2. 195 * 196 * @param moduleType A string that defines the module name in the label for 197 * the value 198 * @param channel The channel number the device is plugged into (usually 199 * PWM) 200 * @param component The reference to the object being added 201 */ 202 public static void addActuator(String moduleType, int channel, LiveWindowSendable component) { 203 addActuator("Ungrouped", moduleType + "[" + channel + "]", component); 204 } 205 206 /** 207 * Add Actuator to LiveWindow. The components are shown with the module 208 * type, slot and channel like this: Servo[1,2] for a servo object connected 209 * to the first digital module and PWM port 2. 210 * 211 * @param moduleType A string that defines the module name in the label for 212 * the value 213 * @param moduleNumber The number of the particular module type 214 * @param channel The channel number the device is plugged into (usually 215 * PWM) 216 * @param component The reference to the object being added 217 */ 218 public static void addActuator(String moduleType, int moduleNumber, int channel, LiveWindowSendable component) { 219 addActuator("Ungrouped", moduleType + "[" + moduleNumber + "," + channel + "]", component); 220 } 221}