The “how” of swerve programming comes down to understanding how to calculate the speeds and angles for each module to move the robot in the desired way. At a high level, the robot’s motion is usually broken into two components: translational (moving in a direction) and rotational (spinning around its center). When you give the robot a set of inputs—like forward, strafe, and rotation—it needs to figure out how to combine these motions and apply them to the four swerve modules.
This is where a lot of the math comes in, like the ChassisSpeeds
and SwerveModuleState
objects in WPILib. When you create a ChassisSpeeds
object, you’re essentially defining how fast the robot should move in X (forward/backward), Y (side to side), and omega (rotation). The SwerveDriveKinematics
class then takes those speeds and calculates the individual speed and angle for each module.
The key is that the kinematics take into account the position of each module relative to the center of the robot. For example, a module on the front-right corner will need to spin at a slightly different speed and angle than a module on the back-left corner when you want to rotate. This is why you set up the Translation2d
objects for each module in the kinematics—those positions define the geometry of your swerve drivetrain.
You’ve probably seen the Rotation2d
and Pose2d
classes a lot. These are super important for keeping track of the robot’s orientation and position on the field. Rotation2d
is used to handle angles in a way that’s easier for the code to work with, and Pose2d
combines both the robot’s position (X and Y) and its rotation. When you use something like SwerveDriveOdometry
, it takes encoder readings and the gyro angle to estimate where the robot is on the field in real-time.
As for controlling the robot, most swerve programs use field-oriented control. This means the robot moves relative to the field, not just itself, which makes it way more intuitive for drivers. To do this, you use the gyro angle to rotate the driver’s inputs (forward, strafe) to match the field’s orientation. That’s why the ChassisSpeeds.fromFieldRelativeSpeeds
method is used—it converts your driver inputs into robot-relative motion based on the gyro.
If you’re using the CTRE swerve project generator, a lot of this should already be set up for you, but understanding these pieces will help you tweak and expand the code. One thing I’d recommend is printing out the module states (angle and speed) while driving. Seeing those numbers change as you give different inputs can really help connect the dots.
To get a deeper understanding, I’d highly recommend the Zero to Autonomous videos on swerve—they’re incredibly beginner-friendly while still covering the advanced stuff you’ll need. The WPILib docs on swerve kinematics and odometry are also really helpful, especially for understanding how the math works behind the scenes.
Finally, don’t be afraid to experiment with the code. Try modifying inputs or writing simple tests to see how the modules react. For example, you could create a function that makes the robot spin in place or strafe diagonally and see how the module angles and speeds adjust. It’s a lot of trial and error.