Subsystems
Here you will learn about subsystems.
Shows options on how to set up a new subsystem. More information on subsystems can be found here
There are three main ways we recommend setting up a subsystem.
This is a simple subsystem setup that includes full logging with no simulation.
public class Arm extends SubsystemBase {
private final LoggableTalonFX armMotor = new LoggableTalonFX(15, "arm");
private final LoggableCANcoder armEncoder = new LoggableCANcoder(16, "arm");
private TalonFXConfiguration armConfig = new TalonFXConfiguration();
/** Creates a new Arm. */
public Arm() {
armConfig.Feedback.FeedbackRemoteSensorID = armEncoder.getDeviceID();
armConfig.Feedback.FeedbackSensorSource =
FeedbackSensorSourceValue.RemoteCANcoder;
armConfig.Feedback.SensorToMechanismRatio = 1;
armMotor.getConfigurator().apply(armConfig, 1);
BaseStatusSignal.setUpdateFrequencyForAll(
50,
armMotor.getVelocity(),
armMotor.getPosition(),
armEncoder.getVelocity(),
armEncoder.getAbsolutePosition());
}
@Override
public void periodic() {}
/** This will most likely be replaced with PID */
public void setSpeed(double speed) {
armMotor.set(speed);
}
}
This is a standard subsystem setup that includes full logging with simulation.
public class Arm extends SubsystemBase {
private static final double kGearRatio = 10.0;
private final LoggableTalonFX armMotor = new LoggableTalonFX(15, "arm");
private final LoggableCANcoder armEncoder = new LoggableCANcoder(16, "arm");
private TalonFXConfiguration armConfig = new TalonFXConfiguration();
private final SingleJointedArmSim m_motorSimModel = new SingleJointedArmSim(
DCMotor.getKrakenX60Foc(2),
kGearRatio,
1.06328,
1,
-3.14 / 2,
3.14 / 2,
true,
Units.degreesToRadians(0.0));
/** Creates a new Arm. */
public Arm() {
armConfig.Feedback.FeedbackRemoteSensorID = armEncoder.getDeviceID();
armConfig.Feedback.FeedbackSensorSource =
FeedbackSensorSourceValue.RemoteCANcoder;
armConfig.Feedback.SensorToMechanismRatio = 1;
armMotor.getConfigurator().apply(armConfig, 1);
BaseStatusSignal.setUpdateFrequencyForAll(
50,
armMotor.getVelocity(),
armMotor.getPosition(),
armEncoder.getVelocity(),
armEncoder.getAbsolutePosition());
}
@Override
public void periodic() {}
@Override
public void simulationPeriodic() {
m_motorSimModel.setInputVoltage(armMotor.getSimState().getMotorVoltage());
m_motorSimModel.update(0.020);
final double position_rot = Units.radiansToRotations(
m_motorSimModel.getAngleRads()) * kGearRatio;
final double velocity_rps = Units.radiansToRotations(
m_motorSimModel.getVelocityRadPerSec()) * kGearRatio;
armMotor.getSimState().setRawRotorPosition(position_rot);
armMotor.getSimState().setRotorVelocity(velocity_rps);
double supplyCurrent = armMotor.getSimState().getSupplyCurrent();
armMotor.getSimState().setSupplyVoltage(12 - supplyCurrent * 0.002);
armEncoder.getSimState().setRawPosition(position_rot / kGearRatio);
armEncoder.getSimState().setVelocity(velocity_rps / kGearRatio);
}
/** This will most likely be replaced with PID */
public void setSpeed(double speed) {
armMotor.set(speed);
}
}
If you need full replay ability, simulation, logging, or the ability to switch hardware types on mechanisms, we recommend using AdvantageKit. An example of AdvantageKit flywheel implementation can be found here
In almost all cases, the next step after choosing your subsystem type is to implement PID and FF.
We recommend following the instructions found here or using SysID.
Last modified: 31 December 2024