Here we wire WPILib's swerve primitives into a drivable teleop subsystem. The core data flow is: joystick inputs -> ChassisSpeeds -> SwerveDriveKinematics -> four SwerveModuleStates -> per-module motors.
Define the geometry#
Kinematics needs the location of each module relative to the robot center. For a 28 in x 28 in frame the wheels sit ~0.29 m from center on each axis:
private static final double X = 0.29, Y = 0.29; // meters
private final SwerveDriveKinematics m_kinematics = new SwerveDriveKinematics(
new Translation2d( X, Y), // front-left
new Translation2d( X, -Y), // front-right
new Translation2d(-X, Y), // back-left
new Translation2d(-X, -Y)); // back-right
Drive method#
Convert joystick demand to chassis speeds (field-relative using the gyro), run kinematics, desaturate so no module is commanded faster than physically possible, then optimize each state so a module never rotates more than 90 degrees:
public void drive(double vx, double vy, double omega) {
ChassisSpeeds speeds = ChassisSpeeds.fromFieldRelativeSpeeds(
vx, vy, omega, m_gyro.getRotation2d());
SwerveModuleState[] states = m_kinematics.toSwerveModuleStates(speeds);
SwerveDriveKinematics.desaturateWheelSpeeds(states, kMaxSpeedMps);
for (int i = 0; i < 4; i++) {
states[i].optimize(m_modules[i].getAngle()); // 2025 instance method
m_modules[i].setDesiredState(states[i]);
}
}
Note the 2025 API change: SwerveModuleState.optimize(currentAngle) is now an instance method that mutates the state in place, replacing the deprecated static SwerveModuleState.optimize(state, angle). (WPILib 2025 also added an instance cosineScale() method on the same class.)
The default command#
Driving is the drivetrain's default behavior, so bind it as the default command -- and remember the rule that a default command must require its subsystem (the run() factory does this automatically):
m_swerve.setDefaultCommand(m_swerve.run(() ->
m_swerve.drive(
-MathUtil.applyDeadband(m_driver.getLeftY(), 0.1) * kMaxSpeedMps,
-MathUtil.applyDeadband(m_driver.getLeftX(), 0.1) * kMaxSpeedMps,
-MathUtil.applyDeadband(m_driver.getRightX(), 0.1) * kMaxOmega)));
Verify before you trust it#
Publish your module states to NetworkTables and open AdvantageScope's Swerve tab, which renders each module's velocity vector, the chassis speeds, and robot rotation. Push the stick forward: all four arrows should point forward and grow together. Rotate: the arrows form a pinwheel tangent to the frame. If one module points the wrong way, its CANcoder offset or motor inversion is wrong -- fix it before driving, not on the field. This visual check catches the single most common swerve bug (a mis-zeroed module) in seconds.
the part worth keeping
Key takeaways
- Swerve data flow: ChassisSpeeds -> toSwerveModuleStates() -> desaturateWheelSpeeds() -> per-module optimize().
- Field-relative driving needs the gyro via ChassisSpeeds.fromFieldRelativeSpeeds().
- In WPILib 2025, SwerveModuleState.optimize() is an instance method that mutates the state in place (the static form is deprecated).
- Validate module states in AdvantageScope's Swerve tab before driving to catch mis-zeroed modules.
Programming, Controls & SensorsWorked Examples and Mini-Projectslesson 3 of 5
Keep going
Take the quiz+10 XP with an accountMore in Worked Examples and Mini-Projects
where this came from
Sources and corrections
This lesson is AI-assisted: drafted from primary sources, then reviewed and edited by hand. Errors still get through. When one is reported we fix it and write down what changed, in public, in the corrections log.
sources and further reading
- docs.wpilib.orgWPILib: Swerve Drive Kinematics
- docs.wpilib.orgWPILib: Swerve Drive Odometry
- docs.advantagescope.orgAdvantageScope: Swerve tab
clipped to this lesson
Articles that go further on this
The lesson gets you through the topic. These go wider on it, and they read in one sitting.
- 13 min readFRC Swerve Module Offsets: Calibration & Backwards WheelsZero your FRC swerve module offsets correctly, and fix wheels that spin backwards, modules that fight each other, and field-relative drive that feels rotated./blogread it
- 20 min readHow to Program FRC Swerve Drive with WPILibA practical guide to programming FRC swerve drive with WPILib: kinematics, SwerveModuleState, field-relative control, odometry, and where PathPlanner fits./blogread it
- 13 min readFRC Code Structure Best Practices: Command-Based Project ArchitectureHow to structure an FRC command-based robot project the right way — subsystems, commands, RobotContainer, and Constants — verified against official WPILib docs./blogread it
answer sheet
Lesson quiz
All 3 right completes the lesson. Miss one and only that question comes back, anything you already answered correctly stays banked.
0 of 3 answered
01What does WPILib's SwerveDriveKinematics convert a ChassisSpeeds object into?
02To make a swerve drive field-relative in teleop, what must you supply in addition to the joystick translation and rotation inputs?
03Why should you call SwerveDriveKinematics.desaturateWheelSpeeds on the module states?
Answer every question to submit.
All 51 lessons in Programming, Controls & Sensorsopenclose
01 / prerequisites
02 / foundations-tools-and-first-program
03 / robot-program-and-command-based
04 / motors-and-control
05 / autonomous-trajectories-simulation
06 / sensing-fundamentals
07 / encoders
08 / gyros-imus-orientation
09 / closed-loop-control
10 / vision-pose-estimation
11 / worked-examples-mini-projects
- Not read yet:Mini-Project: A Closed-Loop Elevator with Motion Magic
- Not read yet:Mini-Project: A Velocity-Controlled Shooter on REVLib
- Not read yet:Mini-Project: A Teleop Swerve Drive Subsystem
- Not read yet:Mini-Project: An Autonomous Routine with PathPlanner
- Not read yet:Mini-Project: Vision-Aligned Scoring with Limelight
12 / common-mistakes-troubleshooting
13 / advanced-techniques-case-studies
- Not read yet:State-Space Control and Kalman Filtering
- Not read yet:Log Replay Architecture with AdvantageKit
- Not read yet:Advanced Pose Estimation: Multi-Tag Fusion and Standard Deviations
- Not read yet:Robot Coordination, Alerts, and Operator Feedback
- Not read yet:Case Study: Hardening Software Before an Event