Skip to content

Subsystems and Commands

Let's look at how our robot code project is structured.

You may noticed that while coding the different subsystems of the robot in robot.java, the file is getting cluttered. To avoid this, we divide our project into different files and folders. Here is another good video explanation of commands and subsystems, or the way we divide up our files. FRC also has a pretty good write-up on command-based programming. The video covers all the fundamentals so it isn't required that you read this. However, the write-ups go into more detail. These resources are crucial and will help you understand nearly everything about writing code for the robot.

Here is an overview of what was explained in the first part of the video plus a few additions.

Note

We'll be assuming that our robot code package is org.team199.robot and our code lives in src/main/java/org/team199 but honestly the package naming scheme varies by year and by team, and it doesn't matter as long as you keep it consistent for a project.

A robot project structure generally looks something like this:

src/main/java/org/team199/
  └── robot2020/
  |   |   Main.java
  |   |   Robot.java
  |   |   RobotContainer.java
  |   |   Constants.java
  |   |
  |   └── subsystems/
  |   |   |   Drivetrain.java
  |   |   |   Intake.java
  |   |   |   Climber.java
  |   |   |   Lift.java
  |   |
  |   └── commands/
  |       |   Drive.java
  |       |   Climb.java
  |       |   RunIntake.java
  |       |   RunEject.java
  |       |   MoveLift.java
  |       |   Autonomous.java
  |
  └── lib/
      |   MotorControllerFactory.java
      |   FancyMathStuff.java
It's a lot, so let's break it down. It may be helpful if you were to look at our previous year's code and follow along this guide.

Main.java

This file is autogenerated, and there is rarely any reason to touch this file at all. It contains the classic main method, which is run at startup and starts up the rest of the robot code.

Robot.java

This file is the control center of the robot. It has the methods that are called to run the robot.

RobotContainer.java

This is where we create and store the objects for the subsystems, then set up all of the default commands and joystick commands that the robot uses to operate. Commands can be mounted to joystick buttons by using the JoystickButton class. Similar buttons are implemented as the JoystickButton class.

new Joystick([insert joystick object], [insert port number]).[insert trigger]([insert command]);
new Joystick(leftJoy, 1).whileHeld(new Intake());
The triggers provided by WPILib are linked here. This is also where we use setDefaultCommand() for each subsystem. In this file, we organize each initialization into different controllers and call all those methods in the constructor of RobotContainer. We also have a getAutonomousCommand() which returns the autonomous command to be called during autonomous mode.

Constants.java

This file contains all of the numbers that don't change and are relevant to the whole robot, not single subsystems. This includes all ports and joystick buttons, which correlate to motor controllers, solenoids, and commands in the code.

Subsystems

Subsystems are where much of the logic of the code is stored. In each subsystem, there are methods that perform certain actions, such as running a motor. These methods are then called in Commands as part of a larger process. For example, a method in the Climber subsystem could be used to retrieve the height of a lift, which can then be called in one of the Climber commands. The subsystem classes contain the objects for the motor controllers and solenoids. Constants for the specific subsystem are also stored in the subsystem class. For example, a constant such as the speed of a drivetrain motor should be stored in the Drivetrain subsystem, as it’s only relevant to the Drivetrain. Subsystems can also have default commands that are run when no commands are implicitly scheduled. Subsystems also have a periodic() which is run every 0.02s no matter what command is called on the subsystem.

Commands

Commands are sections of code that define general actions taken by the robot. Usually, they don’t contain detailed code about the function of the robot’s mechanical parts, such as how far a motor turns or its direction (these finer details are usually placed in subsystems, which commands then reference to give function to each of the robot’s mechanical components). Instead, commands code for actions taken by the robot’s mechanisms. Examples of these actions could include lifting an arm or turning wheels that intake a game piece. Command classes also have methods initialize(), execute(), end(), and isFinished() that serve as a base foundation (More details are in WPILib's article). Each command also have subsystem requirements. This is to avoid scheduling commands that may interfere with each other. For example, one command may want a motor to turn right, while another command wants the motor to turn left. Adding requirements make sure that only one command is using a subsystem at a time. You can add requirements by using the addRequirements().

Lib

The lib folder is where we would store the complex calculations, wrappers, or other things that do not directly interact with the robot, but are rather called on by commands or subsystems to assist in their execution. Stuff in this folder would be valuable code that we would actually want to keep and develop on from one year to another, such as drivetrain characterization, motion profiling, or swerve drive code.

Most of this code is stored in the repository lib199 which is included in the gradle build to our main robot code. This makes it easy to include in new robot projects and other codebases. The lib folder is accessed through gradle build configurations, so you have to directly go the lib199 repo to see the code. It will not be in your project.

MotorControllerFactory.java

This is the most-used file in the lib folder. It stores methods for creating the objects for the motor controllers that are used in the subsystems. Refer to the basic control module if you need review on motor controllers.

WPILib Features

WPILib is the name of the library FRC provides us to control the robot with. Its JavaDocs are located here (and you can also find a link to them in the Resources page of this site). We will be mostly using the library's edu.wpi.first.wpilibj package, and you can search for a class or method using the search bar located on the top right corner of your screen.

WPILib also allows us to use command groups which combine commands together in a desired way. The link provides all the command groups that you can ultilize.