Common Swerve Libraries
This entire unit has built swerve from first principles — which means you now understand every layer that pre-built libraries abstract away. That understanding is exactly what you need to choose the right library for your team, integrate it correctly, and fix it when it misbehaves. This lesson maps the landscape of swerve library options and gives you the mental model to navigate it.
By the end of this lesson, you will:
- Describe the CTRE Phoenix 6 Swerve API (TunerX-generated code) and how it maps to what you've built
- Describe REV MAXSwerve and its SparkMax-based architecture
- Explain the community "BaseFalconSwerve" template pattern and when teams use it
- Use the decision framework to choose between custom code and a pre-built library for a given team context
- Read unfamiliar swerve library code by mapping its concepts to the architecture you've learned
- State the 2910 philosophy on code ownership and why we build before we borrow
Why This Lesson Exists
Most FRC teams don't build swerve from scratch. They use a pre-built library — CTRE's generated code, REV's MAXSwerve example, or a community template. This is entirely reasonable: well-maintained libraries are tested, updated, and documented. Using one isn't cheating — it's pragmatic engineering.
The problem is that teams who use a library without understanding what it does can't fix it when something goes wrong. At competition, at 7 AM, when the robot is doing something unexpected, "I don't know what this code does" is the most dangerous state to be in. The eleven lessons before this one were about building that understanding. Now you can look at any swerve library and see through it.
The Library Landscape
CTRE Phoenix 6 Swerve: What's Under the Hood
CTRE's Tuner X can generate a complete swerve drivetrain from your measured hardware constants. The generated code uses a different paradigm than what you've built — instead of ChassisSpeeds objects, it uses SwerveRequest objects. But it maps directly to the same underlying pipeline.
public static final TunerConstants.SwerveDrivetrain DriveTrain =
new TunerConstants.SwerveDrivetrain(
TunerConstants.DrivetrainConstants,
TunerConstants.FrontLeft,
TunerConstants.FrontRight,
TunerConstants.BackLeft,
TunerConstants.BackRight
);
// SwerveRequest objects replace ChassisSpeeds in commands
private final SwerveRequest.FieldCentric m_driveReq =
new SwerveRequest.FieldCentric()
.withDeadband(MaxSpeed * 0.1)
.withRotationalDeadband(MaxAngularRate * 0.1)
.withDriveRequestType(DriveRequestType.OpenLoopVoltage);
// Command — same driver axis pattern, different output type
private Command driveCommand() {
return drivetrain.applyRequest(() ->
m_driveReq
.withVelocityX(-m_driver.getLeftY() * MaxSpeed)
.withVelocityY(-m_driver.getLeftX() * MaxSpeed)
.withRotationalRate(-m_driver.getRightX() * MaxAngularRate));
}
// The field-oriented transform happens INSIDE SwerveRequest
// The robot's heading is read automatically from the Pigeon 2
// Your fromFieldRelativeSpeeds() call from Lesson 9 is implicit here
CTRE's SwerveRequest pattern combines what you've learned as separate steps: the velocity values (which you computed and passed to drive(ChassisSpeeds)) and the control mode (open-loop voltage vs. velocity closed-loop) are bundled into a single request object. SwerveRequest.FieldCentric handles the fromFieldRelativeSpeeds() rotation internally. If you understand the pipeline from Lessons 3–9, you can read this code fluently.
REV MAXSwerve: SparkMax Architecture
MAXSwerve modules use SparkMax controllers and a REV Through-Bore Encoder on a DIO port for absolute position. The key architectural difference from the CTRE stack: SparkMax PID control runs on the roboRIO over CAN (not onboard the motor controller), so steering latency is slightly higher. For most FRC applications this is immaterial, but understanding it explains some of the tuning differences.
| Feature | 2910 Custom (CTRE) | REV MAXSwerve |
|---|---|---|
| Drive motor | TalonFX (Falcon/Kraken) | SparkMax (NEO/Vortex) |
| Steering motor | TalonFX | SparkMax (NEO 550) |
| Absolute encoder | CANcoder (CAN bus) | Through-Bore (DIO port) |
| Gyro | Pigeon 2 (CAN bus) | ADIS16470 or NavX (SPI) |
| Steering PID location | Onboard TalonFX (1 kHz) | roboRIO via SparkMax (50 Hz) |
| Offset calibration tool | Phoenix Tuner X | REV Hardware Client or code |
| CAN devices per drivetrain | 12 (8 motors + 4 CANcoders + Pigeon) | 8 (8 motors, no CAN encoder) |
The Decision Framework
Reading Library Code You Didn't Write
Whether you adopt a library or inherit code from a previous programmer, the skill of reading unfamiliar swerve code is essential. The mental model from this unit is your decoder ring. For any swerve codebase:
- Find the
drive()entry point — every swerve subsystem has one. Look for a method that accepts velocity inputs and routes them to the module hardware. In CTRE's library, it'sapplyRequest(). In custom code, it's usuallydrive(ChassisSpeeds). This is your anchor. - Trace the kinematics call — find where
toSwerveModuleStates()(or its equivalent) is called. This is the math layer. Confirm it's there and thatdesaturateWheelSpeeds()is applied after it. - Find the module class — every library has a per-module class or record. Find
setDesiredState()(or its equivalent). Confirmoptimize()is called, and that there's a near-zero guard. - Find the constants file — gear ratios, wheel diameter, CAN IDs, offsets. Confirm they match your physical hardware. Wrong constants here produce wrong behavior everywhere.
- Find the odometry/estimator update — look for
update()being called in a periodic method. Confirm the heading is provided with the correct sign convention.
I've watched teams walk into practice day with generated CTRE swerve code that they deployed and haven't read. When something goes wrong — wrong module driving direction, wrong field orientation, offset drift — they don't know where to look. The generated code is excellent starting code. But "generated" doesn't mean "requires no understanding." You still have to know what the constants mean, which direction is positive, and what each request type does. The teams that dominate late in the season are the teams that understand their code regardless of where it came from.
Regardless of which library you use:
- Read the constants file completely. Every constant that maps to physical hardware (gear ratio, wheel diameter, CAN IDs, offsets) must match your specific robot. Generated code uses example values — they must be replaced with measured values.
- Run the single-module isolation test from Lesson 5 before running all four modules. Command one module to 0°, 90°, 180°. Confirm the steering responds correctly. Command a 0.5 m/s drive forward. Confirm the wheel spins the right direction. Do this for each module before full-system testing.
- Confirm the field orientation convention. Push joystick forward → robot drives toward the far wall (not toward your feet). If orientation is reversed, find the library's heading sign convention and correct it.
Knowledge Check
1. A teammate downloads the CTRE Tuner X generated swerve code and deploys it without modifying the constants file. The robot drives, but one module consistently points 47° off from the others. What is almost certainly wrong?
2. REV MAXSwerve runs the steering PID on the roboRIO at 50 Hz rather than onboard the SparkMax. What is the practical consequence compared to onboard Phoenix 6 PID at 1 kHz?
3. You're reading CTRE's generated swerve code and find SwerveRequest.FieldCentric being used. You've never seen this class before. Based on what you learned in this unit, what does it do?
Read and Map an Unfamiliar Swerve Library
- Go to CTRE's swerve example or open the Tuner X generated project for your robot. Find the five architectural elements: the drive entry point, the kinematics call, the per-module class, the constants file, and the odometry update. Write down where each lives (file name, approximate line number). This mapping exercise verifies you understand the structure.
- In the constants file of the chosen library, find the four CANcoder offset values. Compare them to the values you measured in Lesson 2. If they don't match, update them. Re-deploy and confirm the module 47° problem from Q1 doesn't affect your robot.
- Find where the field-to-robot heading rotation is applied in the library you chose. Is it in a
SwerveRequestobject, in the drive command'sexecute(), or somewhere else? Write a one-sentence explanation of how it corresponds to thefromFieldRelativeSpeeds()call you wrote in Lesson 9. - Stretch goal: Read the YAGSL (Yet Another Generic Swerve Library) documentation at
yagsl.gitbook.io. YAGSL supports both CTRE and REV hardware through a JSON configuration system. Identify how it handles the five architectural elements above. Compare its approach to both the custom code from this unit and CTRE's generated code. Which would you choose for a new team and why?