Creating the project
We are not going to create the project from scratch like we did in the Basic Java tutorial. Since the project requires a lot of setup and support files, the easiest way is to copy another project as a template. The project we are going to copy is the RobotIterative project. It would be nice if there were a nice Eclipse wizard to create the project, but in lieu of that, I have create a small Java project called CreateRobotProject which we can use to make a workable copy of the RobotIterative project and then we can import that new project into Eclipse.
To run this program, double click on the CreateRobotProject.jar file in the workspaceJava folder which should display the following dialog box.
In the Project Name field, enter the name of your new project MyMinibot and leave the Template field set to RobotIterative. Then click the Create button. If all goes well, it should create a project named MyRobot.
Once the project has been created, go back to eclipse and choose the File / Import command:
Which will bring up the following dialog:
Open the General options and choose the Existing Projects into Workspace option as shown then click Next.
Then click on the Browse button and choose your MyProject folder which should be in your workspace:
Click OK and this should take you back to the Import dialog with the root directory field set:
Click Finish and your project should be Package Explorer panel on the life.
There is one thing more that we must check before we continue. The version of Java that is running on the robot is 1.7 and we must make sure that we build our project with that version or it will not be able to run. To check this, choose the Preferences option from the Window menu:
Then in the Preferences dialog, open the Java item on the left and click on Compiler and make sure that the Compiler compliance level is set to 1.7 as shown below:
Now open up your project and double click on the Robot.java file to load it into the editor.
Our project has now been created and imported and we are ready to learn how to run it on our robot.
Your program consists of a ‘Robot’ class which inherits from the built in ‘IterativeRobot’ class. Let’s take a look and try and understand the structure of this class:
public class Robot extends IterativeRobot { public static final ExampleSubsystem m_exampleSubsystem = new ExampleSubsystem(); public static OI m_OI = null; Robot() { Logger.Log("Robot", 2, "Robot()"); }
The first thing we see is the declaration of two variables, m_exampleSubsystem, and m_OI. We are going to be using FRC’s Command based system for this program. To use this system, we create classes which inherit from the class Subsystem. Each of these classes that we create will handle a specific subsystem of the robot. For example we will have a subsystem to handle the drive motors. In this program we have an example of a subsystem called ExampleSubsystem which we will used as a model when we create our custom subsystems. Here we instantiate the one and only instance of this subsystem for use by this and all other modules of our program. Later we will look into the details of how these subsystems work when we create the subsystems needed for our Robot.
The next line creates declares a variable of the class OI. This class is used to bind buttons on a controller (e.g. a joystick) to commands that will control the robot. Later we will see exactly how this is done. Note that the m_OI variable is not initialized at this point. This is because we need to wait until the robot is initialized. We will create an instance later in the robotInit function.
Finally, we have the constructor for the class. Once again, we need to be careful as to what we initialize in this constructor. Many elements that we may wish to use should not be instantiated this early in the process. Instead, we should wait for the robotInit function to be called, which brings us to the next code snippet:
/** * Called once to initialize the robot */ @Override public void robotInit() { m_exampleSubsystem.Init(); m_OI = new OI(); }
The robotiInit function will be called once after the internals of the robot are initialized. This is where most of your initialization should take place. Here we call the Init function of the ExampleSubsystem class, so it can initialize it’s data. Note that like our main Robot class, you need to be careful what things you initialize in other classes which may be created before the robot has been initialized.
We also take the opportunity to create an instance of our OI class which is used to bind the controller buttons to commands.
Next we see a set of six functions which are used to control the three modes of the robot, Autonomous, Teleop, and Test.
/* * Called at the start of autonomous mode */ @Override public void autonomousInit() { Logger.ResetElapsedTime(); Logger.Log("Robot", 2, "autonomousInit()"); } /** * Called periodically during autonomous */ @Override public void autonomousPeriodic() { Logger.Log("Robot", -1, "autonomousPeriodic()"); Scheduler.getInstance().run(); Sleep(10); } /** * Called at the start of teleop mode */ @Override public void teleopInit() { Logger.ResetElapsedTime(); Logger.Log("Robot", 2, "teleopInit()"); } /** * Called periodically during operator control */ @Override public void teleopPeriodic() { Logger.Log("Robot", -1, "teleopPeriodic()"); Scheduler.getInstance().run(); Sleep(10); } /** * Called a the start of test mode */ @Override public void testInit() { Logger.ResetElapsedTime(); Logger.Log("Robot", 2, "testInit()"); } /** * Called periodically during test mode */ @Override public void testPeriodic() { Logger.Log("Robot", 0, "testPeriodic()"); Sleep(10); }
The comments in the code are pretty self explanatory. Each of the modes has a function (e.g. autonomousInit) which is called when that mode starts. Then, as long as the robot stays in that particular mode, that mode’s ‘periodic’ function (e.g. autonomousPeriodic) will be repeatedly called.
Finally, we see the following code:
/** * Main program entry point * */ public static void main(String args[]) { Robot Robot = new Robot(); Robot.Start(args); }
This is the main entry point for our program. Here we instantiate our main Robot class, and call the Start function provided by the inherited IterativeRobot class, which starts our robot running.
Before we move on, I would like to bring your attention the the numerous calls to Logger.Log(…). This is a debugging function which allows you to add logging to your program. This can be most useful when trying to figure out why your program is not behaving the way you expect. Later we will see how we can control what information is logged and what is not. I strongly suggest that you make use of this feature when writing your code. It can make finding an elusive problem much easier later, especially when the problem only manifests itself when running the robot in competition.