001/*----------------------------------------------------------------------------*/ 002/* Copyright (c) 2008-2018 FIRST. 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 008package edu.wpi.first.wpilibj; 009 010import java.io.File; 011import java.io.FileOutputStream; 012import java.io.IOException; 013import java.net.URL; 014import java.util.Enumeration; 015import java.util.jar.Manifest; 016 017import edu.wpi.cscore.CameraServerJNI; 018import edu.wpi.first.networktables.NetworkTableInstance; 019import edu.wpi.first.wpilibj.hal.FRCNetComm.tInstances; 020import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType; 021import edu.wpi.first.wpilibj.hal.HAL; 022import edu.wpi.first.wpilibj.hal.HALUtil; 023import edu.wpi.first.wpilibj.internal.HardwareHLUsageReporting; 024import edu.wpi.first.wpilibj.internal.HardwareTimer; 025import edu.wpi.first.wpilibj.livewindow.LiveWindow; 026import edu.wpi.first.wpilibj.util.WPILibVersion; 027 028/** 029 * Implement a Robot Program framework. The RobotBase class is intended to be subclassed by a user 030 * creating a robot program. Overridden autonomous() and operatorControl() methods are called at the 031 * appropriate time as the match proceeds. In the current implementation, the Autonomous code will 032 * run to completion before the OperatorControl code could start. In the future the Autonomous code 033 * might be spawned as a task, then killed at the end of the Autonomous period. 034 */ 035public abstract class RobotBase { 036 /** 037 * The VxWorks priority that robot code should work at (so Java code should run at). 038 */ 039 public static final int ROBOT_TASK_PRIORITY = 101; 040 041 /** 042 * The ID of the main Java thread. 043 */ 044 // This is usually 1, but it is best to make sure 045 public static final long MAIN_THREAD_ID = Thread.currentThread().getId(); 046 047 protected final DriverStation m_ds; 048 049 /** 050 * Constructor for a generic robot program. User code should be placed in the constructor that 051 * runs before the Autonomous or Operator Control period starts. The constructor will run to 052 * completion before Autonomous is entered. 053 * 054 * <p>This must be used to ensure that the communications code starts. In the future it would be 055 * nice 056 * to put this code into it's own task that loads on boot so ensure that it runs. 057 */ 058 protected RobotBase() { 059 NetworkTableInstance inst = NetworkTableInstance.getDefault(); 060 inst.setNetworkIdentity("Robot"); 061 inst.startServer("/home/lvuser/networktables.ini"); 062 m_ds = DriverStation.getInstance(); 063 inst.getTable("LiveWindow").getSubTable(".status").getEntry("LW Enabled").setBoolean(false); 064 065 LiveWindow.setEnabled(false); 066 } 067 068 /** 069 * Free the resources for a RobotBase class. 070 */ 071 public void free() { 072 } 073 074 /** 075 * Get if the robot is a simulation. 076 * 077 * @return If the robot is running in simulation. 078 */ 079 public static boolean isSimulation() { 080 return !isReal(); 081 } 082 083 /** 084 * Get if the robot is real. 085 * 086 * @return If the robot is running in the real world. 087 */ 088 public static boolean isReal() { 089 return HALUtil.getHALRuntimeType() == 0; 090 } 091 092 /** 093 * Determine if the Robot is currently disabled. 094 * 095 * @return True if the Robot is currently disabled by the field controls. 096 */ 097 public boolean isDisabled() { 098 return m_ds.isDisabled(); 099 } 100 101 /** 102 * Determine if the Robot is currently enabled. 103 * 104 * @return True if the Robot is currently enabled by the field controls. 105 */ 106 public boolean isEnabled() { 107 return m_ds.isEnabled(); 108 } 109 110 /** 111 * Determine if the robot is currently in Autonomous mode as determined by the field 112 * controls. 113 * 114 * @return True if the robot is currently operating Autonomously. 115 */ 116 public boolean isAutonomous() { 117 return m_ds.isAutonomous(); 118 } 119 120 /** 121 * Determine if the robot is currently in Test mode as determined by the driver 122 * station. 123 * 124 * @return True if the robot is currently operating in Test mode. 125 */ 126 public boolean isTest() { 127 return m_ds.isTest(); 128 } 129 130 /** 131 * Determine if the robot is currently in Operator Control mode as determined by the field 132 * controls. 133 * 134 * @return True if the robot is currently operating in Tele-Op mode. 135 */ 136 public boolean isOperatorControl() { 137 return m_ds.isOperatorControl(); 138 } 139 140 /** 141 * Indicates if new data is available from the driver station. 142 * 143 * @return Has new data arrived over the network since the last time this function was called? 144 */ 145 public boolean isNewDataAvailable() { 146 return m_ds.isNewControlData(); 147 } 148 149 /** 150 * Provide an alternate "main loop" via startCompetition(). 151 */ 152 public abstract void startCompetition(); 153 154 @SuppressWarnings("JavadocMethod") 155 public static boolean getBooleanProperty(String name, boolean defaultValue) { 156 String propVal = System.getProperty(name); 157 if (propVal == null) { 158 return defaultValue; 159 } 160 if (propVal.equalsIgnoreCase("false")) { 161 return false; 162 } else if (propVal.equalsIgnoreCase("true")) { 163 return true; 164 } else { 165 throw new IllegalStateException(propVal); 166 } 167 } 168 169 /** 170 * Common initialization for all robot programs. 171 */ 172 public static void initializeHardwareConfiguration() { 173 if (!HAL.initialize(500, 0)) { 174 throw new IllegalStateException("Failed to initialize. Terminating"); 175 } 176 177 // Set some implementations so that the static methods work properly 178 Timer.SetImplementation(new HardwareTimer()); 179 HLUsageReporting.SetImplementation(new HardwareHLUsageReporting()); 180 RobotState.SetImplementation(DriverStation.getInstance()); 181 182 // Call a CameraServer JNI function to force OpenCV native library loading 183 // Needed because all the OpenCV JNI functions don't have built in loading 184 CameraServerJNI.enumerateSinks(); 185 } 186 187 /** 188 * Starting point for the applications. 189 */ 190 @SuppressWarnings("PMD.UnusedFormalParameter") 191 public static void main(String... args) { 192 initializeHardwareConfiguration(); 193 194 HAL.report(tResourceType.kResourceType_Language, tInstances.kLanguage_Java); 195 196 String robotName = ""; 197 Enumeration<URL> resources = null; 198 try { 199 resources = RobotBase.class.getClassLoader().getResources("META-INF/MANIFEST.MF"); 200 } catch (IOException ex) { 201 ex.printStackTrace(); 202 } 203 while (resources != null && resources.hasMoreElements()) { 204 try { 205 Manifest manifest = new Manifest(resources.nextElement().openStream()); 206 robotName = manifest.getMainAttributes().getValue("Robot-Class"); 207 } catch (IOException ex) { 208 ex.printStackTrace(); 209 } 210 } 211 212 System.out.println("********** Robot program starting **********"); 213 214 RobotBase robot; 215 try { 216 robot = (RobotBase) Class.forName(robotName).newInstance(); 217 } catch (Throwable throwable) { 218 Throwable cause = throwable.getCause(); 219 if (cause != null) { 220 throwable = cause; 221 } 222 DriverStation.reportError("Unhandled exception instantiating robot " + robotName + " " 223 + throwable.toString(), throwable.getStackTrace()); 224 DriverStation.reportWarning("Robots should not quit, but yours did!", false); 225 DriverStation.reportError("Could not instantiate robot " + robotName + "!", false); 226 System.exit(1); 227 return; 228 } 229 230 try { 231 final File file = new File("/tmp/frc_versions/FRC_Lib_Version.ini"); 232 233 if (file.exists()) { 234 file.delete(); 235 } 236 237 file.createNewFile(); 238 239 try (FileOutputStream output = new FileOutputStream(file)) { 240 output.write("Java ".getBytes()); 241 output.write(WPILibVersion.Version.getBytes()); 242 } 243 244 } catch (IOException ex) { 245 ex.printStackTrace(); 246 } 247 248 boolean errorOnExit = false; 249 try { 250 robot.startCompetition(); 251 } catch (Throwable throwable) { 252 Throwable cause = throwable.getCause(); 253 if (cause != null) { 254 throwable = cause; 255 } 256 DriverStation.reportError("Unhandled exception: " + throwable.toString(), 257 throwable.getStackTrace()); 258 errorOnExit = true; 259 } finally { 260 // startCompetition never returns unless exception occurs.... 261 DriverStation.reportWarning("Robots should not quit, but yours did!", false); 262 if (errorOnExit) { 263 DriverStation.reportError( 264 "The startCompetition() method (or methods called by it) should have " 265 + "handled the exception above.", false); 266 } else { 267 DriverStation.reportError("Unexpected return from startCompetition() method.", false); 268 } 269 } 270 System.exit(1); 271 } 272}