Differential Drive Template
The differential drive template is designed for drives based on Spark Max, Talon FX, or Talon SRX controllers and a NavX, Pigeon 2, or similar gyro. Some of the key features of the template include:
- On-controller feedback loops
- Physics simulation
- Automated characterization routines
- Pose estimator integration (not including vision)
- Deterministic replay with a guarantee of accuracy
The AdvantageKit differential drive template is open-source and fully customizable:
- No black boxes: Users can view and adjust all layers of the drive control stack.
- Customizable: IO implementations can be adjusted to support any hardware configuration (see the customization section).
- Replayable: Every aspect of the drive control logic, pose estimator, etc. can be replayed and logged in simulation using AdvantageKit's deterministic replay features with guaranteed accuracy.
Setup
This example project is part of the 2025 AdvantageKit beta release. If you encounter any issues during setup, please open an issue.
-
Download the differential drive template project from the AdvantageKit release on GitHub and open it in VSCode.
-
Click the WPILib icon in the VSCode toolbar and find the task
WPILib: Set Team Number
. Enter your team number and press enter. -
If not already available, download and install Git.
-
If the project will run only on the roboRIO 2, uncomment lines 39-42 of
build.gradle
. These contain additional garbage collection optimizations for the RIO 2 to improve performance. -
Navigate to
src/main/java/frc/robot/subsystems/drive/DriveConstants.java
in the AdvantageKit project. -
Update the value of
motorReduction
based on the robot's gearing. These values represent reductions and should generally be greater than one. -
Update the value of
trackWidth
based on the distance between the left and right sets of wheels. -
Update the value of
wheelRadiusMeters
to the theoretical radius of each wheel. This value can be further refined as described in the "Tuning" section below. -
Update the value of
maxSpeedMetersPerSec
to the theoretical max speed of the robot. This value can be further refined as described in the "Tuning" section below. -
Set the value of
pigeonCanId
to the correct CAN ID of the Pigeon 2 (as configured using Tuner X). If using a NavX instead of a Pigeon 2, see the customization section below. -
Set values of the left and right leader and follower motors to the correct CAN IDs of the drive controllers (as configured in Phoenix Tuner or REV Hardware Client).
-
In the constructor of
RobotContainer
, switch the IO implementations instantiated for the drive based on your chosen hardware. The default is the Talon SRX and Pigeon 2. -
Deploy the project to the robot and connect using AdvantageScope.
-
Check that there are no dashboard alerts or errors in the Driver Station console. If any errors appear, verify that CAN IDs, firmware versions, and configurations of all devices.
The project is configured to save log files when running on a real robot. A FAT32 formatted USB stick must be connected to one of the roboRIO USB ports to save log files.
- Manually rotate each side of the drive and view the position in AdvantageScope (
/Drive/Module.../DrivePositionRad
). Verify that the units visible in AdvantageScope (radians) match the physical motion of the module, and that positive motion corresponds to forward movement of the robot. If necessary, change the value ofmotorReduction
,leftInverted
, orrighInverted
.
Tuning
Feedforward Characterization
The project includes default feedforward gains for velocity control (kS
and kV
).
The project includes a simple feedforward routine that can be used to quicly measure the drive kS
and kV
values without requiring SysId:
-
Place the robot in an open space.
-
Select the "Drive Simple FF Characterization" auto routine.
-
Enable the robot in autonomous. The robot will slowly accelerate forwards, similar to a SysId quasistic test.
-
Disable the robot after at least ~5-10 seconds.
-
Check the console output for the measured
kS
andkV
values, and copy them to therealKs
andrealKv
constants inDriveConstants.java
.
The feedforward model used in simulation can be characterized using the same method. Simulation gains are stored in the simKs
and simKv
constants.
Users who wish to characterize acceleration gains (kA
) can choose to use the full SysId application. The project includes auto routines for each of the four required SysId tests. Two options are available to load data in SysId:
- For Spark users, the project is configured to use URCL by default. This data can be exported as described here.
- TalonFX (not Talon SRX) users can export the Hoot log file as described here.
- Export the AdvantageKit log file as described here.
Wheel Radius Characterization
The effective wheel radius of a robot tends to change over time as wheels are worn down, swapped, or compress into the carpet. This can have significant impacts on odometry accuracy. We recommend regularly recharacterizing wheel radius to combat these issues.
We recommend the follow process to measure wheel radius:
-
Place the robot on carpet. Characterizing on a hard floor may produce errors in the measurement, as the robot's effective wheel radius is affected by carpet compression.
-
Using AdvantageScope, record the values of
/Drive/LeftPositionRad
and/Drive/RightPositionRad
. -
Manually push the robot directly forwards as far as possible (at least 10 feet).
-
Using a tape measure, record the linear distance traveled by the robot.
-
Record the new values of
/Drive/LeftPositionRad
and/Drive/RightPositionRad
. -
The wheel radius is equal to
linear distance / wheel delta in radians
. The units of radius will match the units of the linear measurement.
Velocity PID Tuning
The project includes default gains for the velocity PID controller, which can be found in the "Velocity PID configuration" section of DriveConstants.java
. These gains should be tuned for each robot.
More information about PID tuning can be found in the WPILib documentation.
We recommend using AdvantageScope to plot the measured and setpoint values while tuning. Measured values are published to the /Drive/LeftVelocityRadPerSec
and /Drive/RightVelocityRadPerSec
fields and setpoint values are published to the /RealOutputs/Drive/LeftSetpointRadPerSec
and /RealOutputs/Drive/RightSetpointRadPerSec
fields.
The PID gains used in simulation can be tuned using the same method. Simulation gains are stored separately from "real" gains in DriveConstants.java
.
Max Speed Measurement
The effective maximum speed of a robot is typically slightly less than the theroetically max speed based on motor free speed and gearing. To ensure that the robot remains controllable at high speeds, we recommend measuring the effective maximum speed of the robot.
-
Set
maxSpeedMetersPerSec
inDriveConstants.java
to the theoretical max speed of the robot based on motor free speed and gearing. -
Place the robot in a open space.
-
Plot the measured robot speed in AdvantageScope using the
/RealOutputs/Drive/LeftVelocityMetersPerSec
and/RealOutputs/Drive/RightVelocityMetersPerSec
fields. -
In teleop, drive forwards at full speed until the robot velocity is no longer increasing.
-
Record the maximum velocity achieved and update the value of
maxSpeedMetersPerSec
.
PathPlanner Configuration
The project includes a built-in configuration for PathPlanner, located in the constructor of Drive.java
. You may wish to manually adjust the robot mass, MOI, and wheel coefficient as configured at the bottom of DriveConstants.java
Customization
Custom Gyro Implementations
The project defaults to the Pigeon 2 gyro, but can be integrated with any standard gyro. An example implementation for a NavX is included.
To change the gyro implementation, switch new GyroIOPigeon2()
in the RobotContainer
constructor to any other implementation. For example, the GyroIONavX
implementation is pre-configured to use a NavX connected to the MXP SPI port. See the page on IO interfaces for more details on how hardware abstraction works.
Custom Motor Implementations
The implementation of ModuleIO
can be freely customized to support alternative hardware configurations, including robot without encoders. For example, the DriveIOSpark
implementation can be customized for brushed motors by changing MotorType.kBrushless
to MotorType.kBrushed
and configuring the encoder counts per revolution by calling config.encoder.countsPerRevolution(...)
.
Vision Integration
The Drive
subsystem uses WPILib's DifferentialDrivePoseEstimator
class for odometry updates. The subsystem exposes the addVisionMeasurement
method to enable vision systems to publish samples.
This project is compatible with AdvantageKit's vision template project, which provides a starting point for implementing a pose estimation algorithm based on Limelight or PhotonVision.