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