The SwerveDrivetrain Subsystem Lesson

The `SwerveDrivetrain` Subsystem

This subsystem is the final piece of our swerve drive puzzle. After building the individual `SwerveModule` class, we need a central hub to manage all four modules, handle odometry, and use kinematics to create cohesive robot movement.

Purpose of the `SwerveDrivetrain`

This class acts as the "brain" of the drivetrain. It orchestrates all the individual components, providing a simple interface for commands to use, like `drive()`, which abstracts away all the complex swerve logic.

Key Responsibilities

  • Manage Modules: It creates and holds the four `SwerveModule` objects.
  • Handle Kinematics: It uses the `SwerveDriveKinematics` object to translate a desired `ChassisSpeeds` into four individual `SwerveModuleState` objects.
  • Update Odometry: In its `periodic()` method, it continuously updates the `SwerveDriveOdometry` with fresh sensor data from the modules and the gyro.
  • Provide Robot Pose: It offers getter methods for commands and other systems to know the robot's current position on the field.

A Complete `SwerveDrivetrain` Subsystem Example

This code demonstrates how the `SwerveDrivetrain` subsystem brings everything together.

public class SwerveDrivetrain extends SubsystemBase {
    // Gyro for heading
    private final Gyro gyro;

    // The four swerve modules
    private final SwerveModule frontLeft, frontRight, backLeft, backRight;

    // Kinematics and Odometry objects from WPILib
    private final SwerveDriveKinematics kinematics;
    private final SwerveDriveOdometry odometry;

    public SwerveDrivetrain() {
        // ... create gyro object ...

        // Create the four module objects
        frontLeft = new SwerveModule(...);
        frontRight = new SwerveModule(...);
        backLeft = new SwerveModule(...);
        backRight = new SwerveModule(...);

        // ... create kinematics object ...
        
        // Create the odometry object, giving it the starting pose
        odometry = new SwerveDriveOdometry(kinematics, gyro.getRotation2d(), getModulePositions(), new Pose2d());
    }

    // This is the main control method for the drivetrain
    public void drive(ChassisSpeeds chassisSpeeds) {
        // Use kinematics to get the desired state for each module
        SwerveModuleState[] moduleStates = kinematics.toSwerveModuleStates(chassisSpeeds);

        // Send the desired state to each module
        frontLeft.setDesiredState(moduleStates[0]);
        frontRight.setDesiredState(moduleStates[1]);
        backLeft.setDesiredState(moduleStates[2]);
        backRight.setDesiredState(moduleStates[3]);
    }

    // This method is called every 20ms
    @Override
    public void periodic() {
        // Update the odometry with the latest sensor readings
        odometry.update(gyro.getRotation2d(), getModulePositions());
    }
    
    public Pose2d getPose() {
        return odometry.getPoseMeters();
    }
}
    

Test Your Knowledge

Question: In which method of the `SwerveDrivetrain` subsystem is the robot's odometry (its estimated position on the field) continuously updated?