Shared Subsystems
Shared Subsystems
Abstract base classes that every concrete subsystem mechanism extends. These bases handle the disabled-subsystem lifecycle, motor management, feedforward estimation, SysId characterization, and motion profiling so concrete subsystems only need to supply their hardware wiring and mechanism-specific behavior.
Hierarchy
AbstractSubsystem<TConfig>
└── AbstractMotorSubsystem<TConfig>
├── AbstractSetAndSeekSubsystem<TConfig>
└── AbstractVelocitySubsystem<TConfig>
Key classes
| File | Role |
|---|---|
AbstractSubsystem.java |
Base class with config, enabled flag, logging, and sim detection |
AbstractMotorSubsystem.java |
Adds a Motor, feedforward, telemetry input processing, and SysId |
AbstractSetAndSeekSubsystem.java |
Trapezoidal motion profile with setTarget / seekTarget flow |
AbstractVelocitySubsystem.java |
Velocity PID + feedforward with setTargetVelocityRpm / seekVelocity |
VisionMeasurementConsumer.java |
Functional interface for accepting vision pose measurements |
SysIdHelper.java |
Factory for building consistent SysIdRoutine instances |
Patterns
Set-and-seek
For mechanisms that move to a target position (turret, climber, harvester):
setTarget(degrees)→ clamps to config limits, logs, and stores the goal.seekTarget()→ steps the trapezoidal profile and applies feedforward + PID voltage.isProfileSettled()→ returns true when position and velocity are within tolerance.
See the turret README for a concrete example.
Velocity
For mechanisms that maintain a target speed (shooter, feeder, indexer, intake):
setTargetVelocityRpm(rpm)→ stores the target with optional acceleration ramping.seekVelocity()→ applies feedforward + PID voltage to track the RPM setpoint.isAtTargetVelocity()→ returns true when the motor speed is within the configured tolerance for the settle time.
SysId characterization
Both motor subsystem types support WPILib SysId via SysIdHelper. The command
factories expose quasistatic and dynamic characterization commands. After
running SysId, use the gains (applying the 2π correction) in the subsystem
config. See SYSID_GUIDE.md for the full workflow.
Disabled-subsystem lifecycle
All subsystems inherit the enabled flag from AbstractConfig. When disabled:
isSubsystemDisabled()returns true.- Public methods return early after calling
logDisabled("methodName"). - Motor-backed subsystems use
DisabledMotorso callers never need null checks. RobotContainerstill constructs every subsystem; they just become inert.