Basic Robot Code Structure

To begin writing code for an FRC robot, first open up FRC VS Code, which we installed earlier.

Once opened, type Ctrl + Shift + P to open up the command palette. Then type “new project” and click “WPILib: Create a new project”:

This will open up the WPILib Project Creator. Here, I’m using the settings shown in the image below (and I recommend that you do the same, modifying the project folder and team number accordingly).

Note: There are different types of projects that can be created. Here, we’re using a program template for the C++ (cpp) language called “Timed Skeleton (Advanced)“.

Once finished creating the project, you should see a project tree that looks something like this:

In the image above, I clicked the arrows next to some of the folders to see their contents. For now, main.cpp, Robot.cpp, and Robot.h are the only files to worry about. Let’s take a looks at each of these.

main.cpp

The main.cpp file looks like this:

#include <hal/HAL.h>

#include "gtest/gtest.h"

int main(int argc, char** argv) {
  HAL_Initialize(500, 0);
  ::testing::InitGoogleTest(&argc, argv);
  int ret = RUN_ALL_TESTS();
  return ret;
}

In our FRC projects, the main.cpp file is only used for running tests on our code, so we won’t look at it that often.

At the top of the file, you’ll see that “hal/HAL.h” and “gtest/gtest.h” are included. HAL.h is used to interact with the robot’s hardware, and it is included for access to the HAL_Initialize function which sets up the robot for later use. gtest.h is included for access to the InitGoogleTest function in the testing namespace. The two colons before “testing” indicate that the namespace is “global” (not inside any other namespace), which is used here just to prevent conflicts with other things that happen to be called “testing“.

This main function also uses command line arguments. Here, argv is used to set settings for how “InitGoogleTest” is run (which performs code tests).

Robot.h

The most important part of our robot’s program is the Robot class, which is split into a header file and a “.cpp” file, like covered earlier. The Robot.h file should look something like this:

#pragma once

#include <frc/TimedRobot.h>

class Robot : public frc::TimedRobot {
 public:
  void RobotInit() override;
  void RobotPeriodic() override;

  void AutonomousInit() override;
  void AutonomousPeriodic() override;

  void TeleopInit() override;
  void TeleopPeriodic() override;

  void DisabledInit() override;
  void DisabledPeriodic() override;

  void TestInit() override;
  void TestPeriodic() override;
};

Earlier, we used “header guards” to prevent header files from being included more than once. Here, “#pragma once” does the same thing, but it’s a bit less to type.

Then, TimedRobot.h is included for access to the TimedRobot class (inside the frc namespace). The Robot class inherits from the TimedRobot class, giving it access to the ten functions found below. It’s our job to override these functions to get the robot to perform different tasks for different game modes.

  • The RobotInit function is automatically called just once when the robot is turned on.
  • The RobotPeriodic function is automatically called repeatedly (multiple times per second) when the robot is turned on.
  • The AutonomousInit function is automatically called just once when autonomous mode begins.
  • The AutonomousPeriodic function is automatically called repeatedly (multiple times per second) during autonomous mode.
  • The TeleopInit function is automatically called just once when teleoperated mode begins.
  • The TeleopPeriodic function is automatically called repeatedly (multiple times per second) during teleoperated mode.
  • The DisabledInit function is automatically called just once when the robot is disabled.
  • The DisabledPeriodic function is automatically called repeatedly (multiple times per second) while the robot is disabled.
  • The TestInit function is automatically called just once when test mode begins.
  • The TestPeriodic function is automatically called repeatedly (multiple times per second) during test mode.

Robot.cpp

In this file, we define what each of the above functions actually do. Right now the file should look like this:

#include "Robot.h"

void Robot::RobotInit() {}
void Robot::RobotPeriodic() {}

void Robot::AutonomousInit() {}
void Robot::AutonomousPeriodic() {}

void Robot::TeleopInit() {}
void Robot::TeleopPeriodic() {}

void Robot::DisabledInit() {}
void Robot::DisabledPeriodic() {}

void Robot::TestInit() {}
void Robot::TestPeriodic() {}

#ifndef RUNNING_FRC_TESTS
int main() { return frc::StartRobot<Robot>(); }
#endif

This file actually contains another main function that’s different from the one in main.cpp. It’s this main function that we’ll be using most of the time, since it actually runs our full robot program (by calling the StartRobot function). To use the main function in main.cpp, the macro “RUNNING_FRC_TESTS” must first be defined (and it isn’t right now).

From this file, you can see that the main function doesn’t need to be in a file called “main.cpp” (or even in its own file at all). As long as the function is in a “.cpp” file, it can be found by the compiler.

Running a Robot Project

Of course, the program we have now does nothing at all since every function in Robot.cpp is empty. Once we start adding code to the project, however, we’ll want to be able to compile it and send the program over to our robot. For these two processes, we use software called Gradle because compiling C++ code and sending it to the robot can become very complex for larger projects.

To compile the program, right click the build.gradle file from the project tree, and press “Build Robot Code”:

To send the program over to the robot, first ensure that the robot is connected to your computer (either via Ethernet or Wi-Fi). Then, right click the build.gradle file and press “Deploy Robot Code”. Note: deploying code to the robot automatically compiles the code as well.

Once code is deployed to the robot, the code can be run by opening the FRC Driver Station and enabling the robot.