2025 FIRST® Robotics Competition
KitBot Java Software Guide
1 Contents
2 Document Overview ....................................................................................................................................... 4
3 Getting Started with your KitBot code ......................................................................................................... 5
3.1 Wiring your robot .................................................................................................................................... 5
3.2 Configuring hardware and development environment .................................................................... 5
3.3 Opening the 2025 KitBot Example ....................................................................................................... 5
3.4 Changing to CAN control .................................................................. Error! Bookmark not defined.
3.4.1 Configuring the SPARK MAXs ................................................... Error! Bookmark not defined.
3.4.2 Installing REVLib .............................................................................................................................. 6
3.4.3 Updating the Code ..................................................................... Error! Bookmark not defined.
3.5 Deploying and testing the KitBot Example .......................................................................................... 7
3.6 Configuring Gamepads .......................................................................................................................... 7
3.7 What does the code do?......................................................................................................................... 7
4 Overall Code Structure ................................................................................................................................... 8
5 Code Walkthrough .......................................................................................................................................... 9
5.1 Subsystems .............................................................................................................................................. 9
5.1.1 PWMDriveSubsystem ..................................................................................................................... 9
5.1.2 CANDriveSubsystem .................................................................. Error! Bookmark not defined.
5.1.3 PWMRollerSubsystem .................................................................................................................. 11
5.1.4 CANRollerSubsystem ................................................................. Error! Bookmark not defined.
5.2 Commands............................................................................................................................................. 11
5.3 Traditional Commands......................................................................................................................... 12
5.3.1 DriveCommand ............................................................................................................................. 12
5.3.2 RollerCommand ............................................................................................................................ 13
5.3.3 AutoCommand .............................................................................................................................. 15
5.4 Factory Commands............................................................................................................................... 16
5.4.1 Drive Command Factory .............................................................................................................. 16
5.4.2 Roller Command Factory ............................................................................................................. 17
5.4.3 Autos ............................................................................................................................................... 17
5.5 Constants ............................................................................................................................................... 17
Rev. Jan 4, 2025 2 of 23
5.6 Robot ...................................................................................................................................................... 17
5.7 RobotContainer ..................................................................................................................................... 18
5.7.1 Imports ........................................................................................................................................... 18
5.7.2 Class definition and Constructor ................................................................................................ 18
6 Making Changes ............................................................................................................................................ 21
6.1 Changing buttons for actions ........................................................... Error! Bookmark not defined.
6.2 Changing Drive Axis Behavior ............................................................................................................. 21
6.3 Changing Drive Type............................................................................................................................. 23
6.4 Developing Autonomous Routines..................................................................................................... 23
Rev. Jan 4, 2025 3 of 23
2 Document Overview
This document will take you through how to get your 2025 KitBot up and running using the provided
Java example code. To avoid content duplication, this document frequently links to WPILib and/or
RobotPy documentation for accomplishing specific steps along the way. In addition to getting you up
and running with the provided code, this document will walk through the structure of that code so you
can understand how it operates. Finally, we’ll walk through some of the most likely changes you may
wish to make to the code and provide concrete examples of how to make those modifications.
To get started with the example code, or to make some of the modifications described, minimal
understanding of Java is required. The code and modification examples provided will likely provide
enough of a pattern to get you going. To understand the walkthrough, or to make modifications not
described in this document, a more thorough understanding of Java is likely required.
This document, and the provided example code, assumes the use of the SPARK MAX controllers
provided in the rookie Kickoff Kit.
Rev. Jan 4, 2025 4 of 23
3 Getting Started with your KitBot code
3.1 Wiring your robot
Use the WPILib Zero-to-Robot wiring document to help you get your robot wired up. The KitBot wiring
and code is documented with the Control System components that have recently come in the Rookie
Kit of Parts (i.e. REV PDH and Spark MAX controllers), the KitBot wiring and code can be adapted to
other electronics but that adaptation is not covered by these documents.
3.2 Configuring hardware and development environment
Before you are able to load code and test out your robot, you will need to configure your hardware
(roboRIO, radio, etc.) and get your development environment set up. Follow the WPILib Zero-to-Robot
guide steps 2 through 4 to get everything set up and ensure you can deploy a basic robot project.
3.3 Opening the 2025 KitBot Example
The 2025 KitBot example code is provided in individual zip files for each language. The Java code
contains two complete projects which illustrate different ways of creating Commands. Some
description of the difference can be found in Ways of creating commands below. To open the Java
code:
1. Download and unzip the Java example code. Make sure to unzip or copy to a permanent
location, not in a temporary folder.
2. Open WPILib VS Code using the Start menu or desktop shortcuts
3. In the top left click File->Open Folder and browse to the “Java” folder inside of the unzipped
example code, then open the desired one of the two example projects, and then click Select
Folder.
3.4 Spark MAX firmware update and CAN IDs
Before using the SPARK MAXs with CAN control, they each need to be assigned a unique ID..
1. Install the REV Hardware Client
2. With the robot powered off, connect a USB cable between the computer and the SPARK MAX
USB port. Leaving the robot powered off ensures only the single SPARK MAX is powered and
avoids changing the IDs on unintended devices.
3. Update the firmware on the SPARK MAX
4. Set the CAN ID and Motor Type (you can skip the current limit) and save the settings
a. CAN IDs for each device can be found in [Link]. You can either set the devices
to match these IDs, or set the IDs as desired (some teams set the CAN ID = the channel
number the device is attached to on the PD) and then update these constants.
b. Note: If you wish to “Spin the motor” as described on that page, make sure the robot is
in a safe state to do so (wheels not touching the ground or table, all hands clear of the
robot).
Rev. Jan 4, 2025 5 of 23
5. Repeat for all 5 devices on the robot. If you’ve wired up the 6th Spark MAX you likely want to set
it to a non-conflicting ID as well.
6. While not required, if using the REV PDH you may wish to check that it has the latest firmware
at this time as well. Do not change the ID of the PDH off of the default, each device type has a
separate ID space and your PDH will not conflict with your SPARK MAX even if set to the same
ID.
Now that all your devices are configured, you can do a preliminary check that your CAN bus is wired
properly using the REV Hardware client. While plugged into any REV device on your CAN bus with a USB
cable, power on the robot and you should see all the other devices listed in the left pane of the REV
Hardware Client, under the CAN Bus heading. If you don’t see all of the devices, you likely have one or
more issues with your CAN bus wiring:
1. Verify that your CAN bus starts with the roboRIO and ends with a 120 ohm resistor, or the built
in terminator of a Power Distribution Hub or Power Distribution Panel (with the termination set
to On using the appropriate jumper or switch).
2. Check that your CAN bus connections all match yellow-yellow and green-green.
3. Check that all CAN wire connections are secure to each other and that the connectors are
securely installed in each SPARK Max
4. If you’re still having trouble, moving the USB connection around to different devices and seeing
what each device can “see” on the bus can help pinpoint the location of an issue.
3.5 Installing REVLib
The software library for the SPARK MAX in CAN mode is provided by the vendor (REV Robotics). The 3rd
party library configuration is already included in the project, but you will have to install the library itself.
There are two ways you can do so:
1. Recommended - Install the library offline – This will ensure that the library persists on your
machine even if you don’t build new code for a while (online installations can be cleaned up
automatically by Gradle).
a. Download the latest version of REVLib using the link from the REV documentation.
b. Unzip into the C:\Users\Public\wpilib\2025 directory on Windows and ~/wpilib/2025
directory on Unix-like systems.
2. Install Online - While the computer is connected to the Internet, click the WPILib icon in the top
right of the VSCode window to bring up the WPILib extension prompt, then start typing “Build
Robot Code” and select that option when it appears. Because the library configuration is
already included in the project, this will automatically fetch the library from the internet.
To install additional Vendor libraries online you can use the WPILib Vendor Library manager inside VS
Code.
Rev. Jan 4, 2025 6 of 23
3.6 Deploying and testing the KitBot Example
To deploy the example to your robot, you will need to set the Team Number on the project. Click the
WPILib icon in the top right corner of the VS Code window (Logo that looks like red and grey ‘<<>>’
symbol) to open the WPILib prompt and start typing “Set Team Number” and select that option when it
appears. Enter your team number (no leading 0s – e.g. 123 or 9996) and press Enter.
You are now ready to deploy the KitBot example just like you deployed the test project in Step 4 of the
Zero-to-Robot guide.
Warning: Make sure you have space in all directions when operating a robot. Even with known code,
the robot may move with unexpected speed or in unexpected directions. Be prepared to Disable
(Enter) or E-stop (Spacebar) the robot if necessary. The 2025 KitBot code contains a very simple
autonomous routine that will move the robot forwards at ½ speed for 1 second when the robot is
enabled in Autonomous mode.
3.7 Configuring Gamepads
The code is set up to use the Xbox controller class. The Logitech F310 gamepads provided in the Kit of
Parts will appear like Xbox controllers to the WPILib software if they are configured in the correct
mode. To set up the controllers, check that the switch on the back of the controller is set the ‘X’ setting.
Then when using the controller, make sure the LED next to the Mode button is off; if it is on press the
Mode button to toggle it. When the Mode light is on, the controller swaps the function of the left
Analog stick and the D-pad.
3.8 What does the code do?
The provided code implements the following robot controls in Teleoperated:
- Driver controller is an Xbox Controller in Slot 0 of the Driver Station
o Controls the robot drivetrain using Split-stick Arcade Drive
Y-axis (vertical) of left stick controls forward-back movement of drivetrain
X-axis (horizontal) of right stick controls rotation of drivetrain
- Operator controller is an Xbox controller in Slot 1 of the Driver Station
o Controls the gamepiece roller using the triggers and buttons
Left Trigger – Runs the roller motor inward (tries to push the Coral back up the
ramp) at variable speed.
Right Trigger – Runs the roller motor outward (tries to eject the Coral) at variable
speed.
A-Button – Runs the roller motor outward at specific power.
Because of the way the code is implemented, it is not recommended to press the triggers at the same
time as the behavior will be difficult to predict. Pressing the left and right triggers at the same time will
add their values together. For example, pressing the left trigger down halfway, and the right trigger
down all the way, the result will be the motor spinning outward at ½ speed.
Rev. Jan 4, 2025 7 of 23
4 Overall Code Structure
The provided code utilizes the Command-Based programming structure provided by WPILib. This
structure breaks up the robot’s actuators into “subsystems” which are controlled by “commands” or
collections of commands (aptly name “command groups”). The Command-Based structure may be a bit
overkill for a robot of this complexity, but it scales very well for teams looking to add additional
functionality to their KitBot. Additionally, this code structure was used by over 60% of teams in 2024,
increasing the likelihood that teams around you may be able to provide assistance before or during the
event.
To read more about the Command-Based structure, see the Command-Based Programming chapter of
the WPILib documentation.
4.1 Ways of creating commands
There are multiple ways that you can define commands within the Command-Based structure. This
project uses two of these different types to provide exposure to what they would look like in a full
robot project. The common ways of creating commands that are utilized in this project are:
- Traditional: Command/group is defined as its own class in its own file.
- Factory: Command/group is defined via a “Command Factory method” in the subsystem or a
separate static command class.
Traditional Factory
Generally easier to understand Slightly high learning curve
Modularity – Commands can be long Modularity – Commands are broken down
depending on the complexity into small pieces and strung together into
groups
Boilerplate – Command classes require Boilerplate – Commands are written as
subclassing and can be long methods in the subsystem, meaning less
unnecessary code
Organization – Having many Command Organization – Commands are grouped
classes can cause clutter and slow together based on the subsystems they
programmer’s efficiency require, leading to fewer/no dedicated
Command classes
Debugging – Easier to debug due to more Debugging – More difficult to debug due to
defined structure and traditional logic the lambda functions and command
compositions
Rev. Jan 4, 2025 8 of 23
5 Code Walkthrough
5.1 Subsystems
As described in the What is Command-Based Programming article, “’subsystems’ represent
independently-controlled collections of robot hardware (such as motor controllers, sensors, pneumatic
actuators, etc.) that operate together”.
For the 2025 KitBot we have 5 motors that make up 2 subsystems, the Drivetrain, and the Roller. The 4
motors in the drivetrain always need to be working together to move the robot around the field and
the Roller motor must spin to manipulate Pipes.
Sometimes the boundaries between subsystems may not be so clear, if you have an arm with a
shoulder and wrist joint and a set of motorized wheels on the end, is that all one subsystem or
multiple? The general rule of thumb to follow is think about what actions, or commands, you might
have to control the subsystems. Do you think you might want the two pieces to be controlled
independent of each other (i.e. run the intake in or out while moving the arm or wrist?). If you’re
unsure, err towards more smaller subsystems; you can always make commands that require multiple
subsystems but if you end up wanting separate commands to control a single subsystem at the same
time, you’ll have to refactor the subsystem to split it up.
5.1.1 CANDriveSubsystem
This class is the subsystem for the drivetrain.
[Link] Imports
This section declares what other classes or packages we need to reference within this code (imports). A
common practice is to add imports as you go; as you find yourself referencing a class you have not yet
imported, you can add an import for that class. The first group of imports in this subsystem is from the
REV Robotics library for various items we need to reference for the Spark MAXs. The second group is
WPILib classes (one for the type of drivetrain on the robot and one for subsystems) and the
DriveConstants section of the Constants file from this project.
Rev. Jan 4, 2025 9 of 23
If you’re using the InlineCommands version of the project you’ll see a few more imports for some
WPILib Command classes as well as one at the top for a Java class called “DoubleSupplier” which is how
you’ll pass changing values into the commands.
[Link] Class declaration, and Member Variables
The first line of this image is the class declaration. This declares the name of our class and says that it’s
an extension of the SubsystemBase class. All subsystems should extend this class which provides some
utility functions regarding setting the name of the subsystem, registering it with the scheduler, and
sending information about it to the dashboard.
[Link] Constructor
The next section is the constructor. In the first part of the constructor we initialize any variables
contained in the subsystem. In the case of our drivetrain, we initialize the 4 motor controllers and add
one controller for each side into a WPILib DifferentialDrive object which describes the whole drivetrain.
The remainder of the constructor (not pictured) sets up the SparkMAXs for the drivetrain. One motor
on each side is set as a follower and directed to follow the leader, then the leader motors are
configured with some additional details. Review the comments for what settings are being configured
and why.
[Link] Methods
The remainder of the subsystem class is methods. Here we define any methods that commands may
need to call to get status from or perform actions on the subsystem. For our simple drivetrain, the only
method we need is the arcadeDrive method which simply passes the parameters through to the same
method on the DifferentialDrive object.
Rev. Jan 4, 2025 10 of 23
In the InlineCommands version of the project this method will look a little different, for more detail see
the Factory Commands section.
5.1.2 CANRollerSubsystem
This class is the subsystem for the roller mechanism.
[Link] Package, Imports, Class Declaration, Member Variables, and Constructor
The first sections of this subsystem are very similar to the Drive subsystem. See that section for more
detailed description of each of these parts of the code. For the launcher, the single motor is created
and controlled independently, no follower or drivetrain object is used.
[Link] Methods – Hardware Control
The remainder of the subsystem class is hardware access methods. Here we define any methods that
commands may need to call to get status from or perform actions on the subsystem. For our roller this
includes methods to set the speed of the axle.
In the InlineCommands version of the project this method will look a little different, for more detail see
the Factory Commands section.
5.2 Commands
Commands are what tell the robot when to run the different components that are defined in their
subsystems. Commands are “scheduled” for execution, performed, and then removed from the
command scheduler. Each command has 4 distinct parts that are performed throughout its lifecycle:
- Initialize: performed when the command is initially scheduled. Anything put in the initialize
section of a command will run right before the main body of the command.
- Execute: the main body of the command, which runs once every loop cycle (~20 ms)
- End: performed when the command is removed from the scheduler which will occur when the
command indicates it’s finished or if it’s interrupted by a new command requiring one of the
same subsystems.
- isFinished: called once per loop cycle after the execute method. isFinished returns true when
the condition for exiting the command is met. When isFinished returns true, the end method is
called.
As we discussed in section 4, the two ways of writing commands that we focus on in this tutorial are
Traditional commands which subclass the WPILib Command class, and command factories, which use
command decorators to create commands. Regardless of the way your team chooses to make
commands, this is the underlying structure that commands follow.
Rev. Jan 4, 2025 11 of 23
5.3 Traditional Commands
This subsection will focus on the Traditional command-based framework. Traditional commands are
defined in their own classes by subclassing the generic WPILib Command. This means that we can
directly override the behavior of the command methods.
5.3.1 DriveCommand
[Link] Imports and Constructors
The constructor of the command simply stores some parameters into class variables for later use and
declares the subsystem the command requires using “addRequirements”. All commands should have
an “addRequirements” indicating any subsystems they will call methods on that control outputs (i.e.
you may call methods to get values from a subsystem without requiring it but should not set values)
Rev. Jan 4, 2025 12 of 23
[Link] Methods – Command State Overrides
In the execute method, we call the ArcadeDrive method from the drive subsystem which tells the
motors to drive such that the robot moves according to the joystick inputs. If you don’t have any code
in a particular command method (such as “initialize” and “end” here) it is permitted to delete them, the
base Command class includes a blank implementation that will be used if your class doesn’t have an
Override.
5.3.2 RollerCommand
The first section of this command is very similar to the Drive command. See section 5.3.1 for more
detailed description of each of the parts of the code.
Rev. Jan 4, 2025 13 of 23
[Link] Imports and Constructor
[Link] Methods – Command State Overrides
In the roller command execute() the roller is set to the values retrieved from the suppliers that are
passed in. The provided code uses this command two ways, as a default command where values are
retrieved from the triggers, and as mapped to a button where the values are provided as constants.
Note that the end() method is empty meaning that the command does not explicitly stop the motor
Rev. Jan 4, 2025 14 of 23
when it ends. This works in the provided code because as soon as the button version ends, the default
command version will start running and stop the motors if the triggers aren’t being pressed. If you
start using this command in autonomous, you may notice the roller not stopping when expected,
adding some code to the end method here is how you would clean that up!
5.3.3 AutoCommand
The AutoCommand is slightly different from the other two commands, as it requires a little bit more
setup.
[Link] Imports and Constructor
The AutoCommand constructor takes a drive subsystem parameter, and instantiates two member
variables to track the state of the auto routine.
Rev. Jan 4, 2025 15 of 23
[Link] Methods – Command State Overrides
- Initialize: Start the timer.
- Execute: Sets the drive motors to drive forward.
- End: Stop the timer and stop the drive subsystem.
- IsFinished: Returns true when the timer exceeds 1 second.
5.4 Factory Commands
This subsection will focus on the factory command-based framework. Commands are defined in their
subsystems using WPILib inline commands and decorators.
5.4.1 Drive Command Factory
The drive command factory is a method in the Drive subsystem which creates a command. We call in
the RobotContainer to set it as the default command for the drive subsystem.
Rev. Jan 4, 2025 16 of 23
5.4.2 Roller Command Factory
This section is very similar to the Drive Command Factory section. If you want more details on how the
command-based factories work, see Section 5.4.1.
5.4.3 Autos
The Autos file is an example of a “Static Command Factory”. Your program should never create an
Autos object (as shown by the constructor simply printing an error message), instead you call class
methods statically using [Link]() type syntax. This structure is one of the ways to define
complex groups that involve multiple subsystems (though our example here is not complex and
requires only a single subsystem).
Our example file only has a single autonomous routine to get. You could easily extend this pattern by
adding additional methods to define more autonomous routines and you could select between them
using a SendableChooser on the dashboard.
This simple autonomous routine instructs the robot to drive forwards for 1 second at 50% power by
using the WithTimeout decorator to set a timeout of 1 second on the driving command. The different
types of command compositions that are built-in via decorators and factory methods are described on
the Command Compositions page.
5.5 Constants
This class contains named constants used elsewhere in the code. Subclasses are used to organize the
constants into distinct groups, in this case by subsystem. The provided constant names should pretty
clearly describe what each is for.
5.6 Robot
This file is identical to the default Command-Based template. You can find a description of the
elements in the Robot class in the Structuring a Command-Based Robot Project article.
Rev. Jan 4, 2025 17 of 23
5.7 RobotContainer
The RobotContainer class is where instances of the robot subsystems and controllers are declared and
where default commands and mappings of buttons to commands are defined.
5.7.1 Imports
The first section of code is the imports. In this case we need to import some elements from the
commands module, the constants file from our project, and then all of our commands and
subsystems.
5.7.2 Class definition and Constructor
The first section of the class sets up some member variables in the class. For RobotContainer this
generally includes all of your subsystems and control devices. This code uses the
Rev. Jan 4, 2025 18 of 23
CommandXboxController class to represent the gamepads as it contains a number of helper methods
that make it much easier to connect commands to buttons.
Next is the constructor which contains a call to configureBindings() which we will cover below. This
method is used to set up button bindings and default commands. You could put all this code directly in
the constructor, but as your robot and controls become more complex, it’s often helpful to split things
up for clarity.
The other thing the constructor does is add the one autonomous mode to the dashboard chooser.
Additional autonomous mode options can be added to this chooser using the adoption() method and
then you could select which one to run from SmartDashboard, Shuffleboard, Elastic or other 3rd part
dashboards.
5.7.3 configureBindings()
This method sets up the relationships between our controls and commands.
The first section sets up a binding for the ‘A’ button on the operator controller. The
CommandXboxController class contains methods for each button which return “Trigger” objects. These
“Trigger” objects then have further methods that narrow down the behavior we want to control the
command such as toggles, initiating on change, or running only while the Trigger is true or false. In this
instance we use “whileTrue()” to have our command run while the button is being held and stop when
it is released. Because our RollerCommand takes DoubleSupplier types as it’s parameters (so that it
can retrieve changing joystick values in the other usage of it), we need to use a lambda function to pass
the constant values.
Rev. Jan 4, 2025 19 of 23
The provided code also sets default commands in the configureBindings method. The choice of where
to do this is personal preference. As your robot and controls get more complex, you may prefer to put
the default command mapping in the constructor or even split it into it’s own method called from the
constructor.
Next, we set up the default command for the drivetrain. We want a command to run on our drivetrain
to allow us to drive the robot with joysticks whenever we don’t have some other command using the
drivetrain (like the exampleAuto command). To do this we use the setDefaultCommand() method of
the subsystem. This sets the command that will run whenever the Scheduler sees nothing else running
on that subsystem.
We use our DriveCommand and again pass it data using lambdas, but in this case that data is functions
of the driverController that the command will call each time it wants new data. For the forward/back
movement we pass in the value from the Y-axis (vertical) of the left stick of the controller, but we
negate it. This is because joysticks generally define pushing the stick away from you as negative and
pulling the stick towards you as positive (a result of the original use being flight simulators). We want
pushing the stick away from us to drive the robot forward so we negate the value. Similar for the
turning value where we negate the X-axis (horizontal) of the right stick of the controller. The joystick
considers pushing this to the right as a positive value, but the WPILib classes consider clockwise
rotation (what would be expected when pushing the joystick right) as negative.
The binding for the roller subsystem looks like this:
Or
This sets the roller command to get its forward value from the left trigger and its reverse value from
the left trigger. This is the configuration we found to be intuitive in testing, so the right hand always
ejects the Coral (right trigger + A button) and the left hand reverses the roller (pushing the Coral back
up the ramp). Changing the controller mapping is one the easiest code changes to make, so feel free to
experiment and see what you like! For more information on how to do this, see the Making Changes
section directly below.
Rev. Jan 4, 2025 20 of 23
6 Making Changes
This section details some common possible changes you may want to make to the KitBot code and
provides some references for how to approach making those changes.
6.1 Changing buttons for actions
One of the easiest changes to make to Command-Based robot code is to switch what buttons or
button behaviors control a command. The commands used in the 2025 KitBot do not end (isFinished
always returns false) so they should generally only be used with the whileTrue() behavior, but changing
which buttons they map to can be done very simply.
The button mappings in the example code are done near the end of the configureBindings() method
inside the RobotContainer file. The bindings used for this project are made using the helper methods
of the CommandXboxController class. These helper methods exist for each button on the controller
and return a Trigger object which has further methods that can be used to specify a behavior for the
binding.
As provided the code connects the a button to the fixed power. To change this, simply change the a()
helper method to the method for any of the other buttons! You can see all of the available options by
looking through the CommandXboxController Javadoc for methods which take no parameter and
return a Trigger object.
For example, to change the intake command from the a bumper to the x button, simply replace the a()
with x()
6.2 Changing Drive Axis Behavior
Another easy change to make is to modify which axes of the controller are used as which part of the
robot driving and how. The provided code does this mapping when setting up the drivetrain default
command at the end of the configureBindings in RobotContainer.
The example code uses the Y-axis of the left stick to drive forward and back and the X-axis of the right
stick to rotate. These can easily be swapped to the opposite sticks, or move just one so they are on the
same stick! To review the available options, look for methods that return a float in the XboxController
API Doc. To make this type of modification, locate the method call you wish to change, such as
getLeftY(), and replace it with the new desired method, such as getRightY()
Rev. Jan 4, 2025 21 of 23
Example: changing the forward-back driving to the right stick Y-axis and leaving the rotation on the
right X-axis
You can also modify the axis values. One common modification is to cube the values. This preserves
the sign of the value (positive stays postive, negative stays negative) and the maximum value (doesn’t
reduce the max speed of the robot) while providing less sensitivity at low inputs, potentially allowing
for more precise control at low speeds. To make this type of modification, you can apply the
modification to the axis where it’s being captured. The Arcade Drive method from the Differential Drive
class already squares the inputs by default (while preserving sign), you likely want to disable this if you
are cubing them yourself by passing an additional parameter to the Arcade Drive method call in the
drivetrain subsystem.
Example: changing only the rotation axis to be cubed:
Another common modification is to scale the values down by default, but allow for the maximum value
if a button is pressed (turbo mode). This type of modification can also be done at the point of capture,
though as complexity grows, you may wish to shift from an inline command definition to a different
type where you can define the command behavior more clearly.
Example: Scale the forward-back driving by 50% unless the right bumper is pressed
This example uses a shorthand if else construction called the ternary operator. This operator allows us
to write a simple “if” statement in a very compact way, if the right bumper is pressed, we pass the full
value, if not we multiply it by .5. The code also uses a method called “getHID()” on the
CommandXboxController; this method gives use the underlying XboxController object which we use to
get the direct Boolean value of the button instead of the Trigger objects that come from the
CommandXboxController class.
Rev. Jan 4, 2025 22 of 23
6.3 Changing Drive Type
The last likely change we will cover is changing from Arcade Drive to Tank Drive. Unlike Arcade drive
which maps one axis to rotation and one to forward/back, Tank drive maps one axis (generally the Y-
axis) to each side of a differential drivetrain. To make this change, you’ll have to reach beyond
RobotContainer as the provided drivetrain subsystems don’t expose a tank drive method. In the
drivetrain subsystem make a new method called tankDrive(). This method should look a lot like the
arcadeDrive method. Then, modify the default command mapping in RobotContainer to use this new
method with the appropriate joystick axis.
Example:
6.4 Developing Autonomous Routines
The provided code contains a very basic autonomous mode that drives forward at ½ power for 1
second. Additional autonomous modes can be developed, either by adding additional methods in the
Autos file (see the Hatchbot Inlined example project for an example of this style with more complex
autonomous) or by creating separate files for each autonomous routine (see the Hatchbot Traditional
for an example of this approach).
It's common (but definitely not required!) to have multiple autonomous routines that you may wish to
run based on different starting locations or strategies. If you pursue this, the most common way to
choose between them for each match is to select between them using a SendableChooser on the
dashboard.
Rev. Jan 4, 2025 23 of 23