Subsystems

Overview

Subsystems encapsulate hardware (motors, sensors) and provide methods to control them. They extend SubsystemBase and should contain minimal logic—just the 'how' to control hardware.

Subsystem Principles

Best practices:

  • Encapsulation: Hide hardware details from commands.
  • Methods: Provide simple, focused control methods.
  • No Complex Logic: Commands handle when and why; subsystems handle how.
  • Configuration: Set up hardware in the constructor.

Intake Subsystem Example

A basic subsystem with motor configuration:
package frc.robot.subsystems;

import edu.wpi.first.wpilibj2.command.SubsystemBase;
import com.ctre.phoenix6.hardware.TalonFX;
import com.ctre.phoenix6.configs.TalonFXConfiguration;
import com.ctre.phoenix6.signals.NeutralModeValue;
import com.ctre.phoenix6.controls.DutyCycleOut;

public class Intake extends SubsystemBase {
    private final TalonFX m_motor = new TalonFX(5);
    private final DutyCycleOut m_out = new DutyCycleOut(0);
    
    public Intake() {
        TalonFXConfiguration config = new TalonFXConfiguration();
        config.MotorOutput.NeutralMode = NeutralModeValue.Coast;
        config.CurrentLimits.StatorCurrentLimitEnable = true;
        config.CurrentLimits.StatorCurrentLimit = 30.0;
        m_motor.getConfigurator().apply(config);
    }
    
    public void run(double speed) {
        m_motor.setControl(m_out.withOutput(speed));
    }
    
    public void stop() {
        m_motor.setControl(m_out.withOutput(0));
    }
}

Default Commands

Subsystems can have a default command that runs when no other command requires the subsystem. Use setDefaultCommand() in RobotContainer to set one.

Resources

Open full interactive app