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