001 /* 002 * To change this template, choose Tools | Templates 003 * and open the template in the editor. 004 */ 005 package edu.wpi.first.wpilibj.livewindow; 006 007 import edu.wpi.first.wpilibj.command.Scheduler; 008 import edu.wpi.first.wpilibj.networktables.NetworkTable; 009 import edu.wpi.first.wpilibj.tables.ITable; 010 import java.util.Enumeration; 011 import java.util.Hashtable; 012 import 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 */ 020 class 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 */ 051 public 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 = NetworkTable.getTable("LiveWindow"); 057 private static ITable statusTable = livewindowTable.getSubTable("~STATUS~"); 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 for (Enumeration e = components.keys(); e.hasMoreElements();) { 071 LiveWindowSendable component = (LiveWindowSendable) e.nextElement(); 072 LiveWindowComponent c = (LiveWindowComponent) components.get(component); 073 String subsystem = c.getSubsystem(); 074 String name = c.getName(); 075 System.out.println("Initializing table for '" + subsystem + "' '" + name + "'"); 076 livewindowTable.getSubTable(subsystem).putString("~TYPE~", "LW Subsystem"); 077 ITable table = livewindowTable.getSubTable(subsystem).getSubTable(name); 078 table.putString("~TYPE~", component.getSmartDashboardType()); 079 table.putString("Name", name); 080 table.putString("Subsystem", subsystem); 081 component.initTable(table); 082 if (c.isSensor()) { 083 sensors.addElement(component); 084 } 085 } 086 } 087 088 /** 089 * Set the enabled state of LiveWindow. If it's being enabled, turn off the 090 * scheduler and remove all the commands from the queue and enable all the 091 * components registered for LiveWindow. If it's being disabled, stop all 092 * the registered components and reenable the scheduler. TODO: add code to 093 * disable PID loops when enabling LiveWindow. The commands should reenable 094 * the PID loops themselves when they get rescheduled. This prevents arms 095 * from starting to move around, etc. after a period of adjusting them in 096 * LiveWindow mode. 097 */ 098 public static void setEnabled(boolean enabled) { 099 if (liveWindowEnabled != enabled) { 100 if (enabled) { 101 System.out.println("Starting live window mode."); 102 if (firstTime) { 103 initializeLiveWindowComponents(); 104 firstTime = false; 105 } 106 Scheduler.getInstance().disable(); 107 Scheduler.getInstance().removeAll(); 108 for (Enumeration e = components.keys(); e.hasMoreElements();) { 109 LiveWindowSendable component = (LiveWindowSendable) e.nextElement(); 110 component.startLiveWindowMode(); 111 } 112 } else { 113 System.out.println("stopping live window mode."); 114 for (Enumeration e = components.keys(); e.hasMoreElements();) { 115 LiveWindowSendable component = (LiveWindowSendable) e.nextElement(); 116 component.stopLiveWindowMode(); 117 } 118 Scheduler.getInstance().enable(); 119 } 120 liveWindowEnabled = enabled; 121 statusTable.putBoolean("LW Enabled", enabled); 122 } 123 } 124 125 /** 126 * The run method is called repeatedly to keep the values refreshed on the screen in 127 * test mode. 128 */ 129 public static void run() { 130 updateValues(); 131 } 132 133 /** 134 * Add a Sensor associated with the subsystem and with call it by the given 135 * name. 136 * 137 * @param subsystem The subsystem this component is part of. 138 * @param name The name of this component. 139 * @param component A LiveWindowSendable component that represents a sensor. 140 */ 141 public static void addSensor(String subsystem, String name, LiveWindowSendable component) { 142 components.put(component, new LiveWindowComponent(subsystem, name, true)); 143 } 144 145 /** 146 * Add an Actuator associated with the subsystem and with call it by the 147 * given name. 148 * 149 * @param subsystem The subsystem this component is part of. 150 * @param name The name of this component. 151 * @param component A LiveWindowSendable component that represents a 152 * actuator. 153 */ 154 public static void addActuator(String subsystem, String name, LiveWindowSendable component) { 155 components.put(component, new LiveWindowComponent(subsystem, name, false)); 156 } 157 158 /** 159 * Puts all sensor values on the live window. 160 */ 161 private static void updateValues() { 162 //TODO: gross - needs to be sped up 163 for (int i = 0; i < sensors.size(); i++) { 164 LiveWindowSendable lws = (LiveWindowSendable) sensors.elementAt(i); 165 lws.updateTable(); 166 } 167 // TODO: Add actuators? 168 // TODO: Add better rate limiting. 169 } 170 171 /** 172 * Add Sensor to LiveWindow. The components are shown with the module type, 173 * slot and channel like this: Gyro[1, 2] for a gyro object connected to the 174 * first analog module in channel 2 175 * 176 * @param moduleType A string indicating the type of the module used in the 177 * naming (above) 178 * @param moduleNumber The number of the particular module type 179 * @param channel The channel number the device is connected to 180 * @param component A reference to the object being added 181 */ 182 public static void addSensor(String moduleType, int moduleNumber, int channel, LiveWindowSendable component) { 183 addSensor("Ungrouped", moduleType + "[" + moduleNumber + "," + channel + "]", component); 184 if (sensors.contains(component)) { 185 sensors.removeElement(component); 186 } 187 sensors.addElement(component); 188 } 189 190 /** 191 * Add Actuator to LiveWindow. The components are shown with the module 192 * type, slot and channel like this: Servo[1,2] for a servo object connected 193 * to the first digital module and PWM port 2. 194 * 195 * @param moduleType A string that defines the module name in the label for 196 * the value 197 * @param moduleNumber The number of the particular module type 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 moduleNumber, int channel, LiveWindowSendable component) { 203 addActuator("Ungrouped", moduleType + "[" + moduleNumber + "," + channel + "]", component); 204 } 205 }