Architecture¶
The code is organized around one rule: commands depend on robot behavior, not vendor hardware. That rule is what lets the same command work on the real robot, in sim, and during replay.
Composition root¶
RobotContainer is the composition root. It creates subsystems, selects real/sim/replay IO implementations, binds driver controls, and exposes the selected autonomous command.
Keep construction decisions there. If a subsystem needs different IO in real mode and sim mode, choose it in RobotContainer or in a small factory called by RobotContainer.
Subsystems own behavior¶
A subsystem should expose methods in the language of the robot:
public void setIntakeVoltage(double volts)
public boolean hasGamePiece()
public Command intakeUntilDetected()
Avoid exposing methods in the language of a device:
Device objects belong behind IO boundaries. Commands should not know which motor controller, camera, or sensor is installed.
IO owns hardware details¶
The drivetrain shows the intended pattern:
Driveowns behavior and odometry fusion.Moduleowns one swerve module abstraction.ModuleIOdescribes inputs and outputs.ModuleIOTalonFXtalks to real CTRE hardware.ModuleIOSimsimulates behavior.- Empty IO implementations make replay safe.
Use the same shape for mechanisms when hardware behavior is non-trivial. For a very simple prototype, a direct subsystem may be acceptable temporarily, but the production version should still have a replay-safe design.
Commands are small¶
Commands should coordinate behavior. They should not contain vendor configuration, raw CAN logic, camera parsing, or drivetrain kinematics.
Good commands:
- read operator intent
- call subsystem methods
- compose other commands
- apply timeouts
- express finish conditions
Bad commands:
- construct motor controllers
- parse NetworkTables camera data
- configure PID slots
- directly reset module encoders
- silently change navigation policy based on vision health
Drivetrain public surface¶
Commands use Drive for:
- current pose
- robot-relative speeds
- field-relative teleop driving
- robot-relative driving
- pose reset
- module orientation and X-lock
- characterization commands
- timestamped vision measurement ingestion
That API is intentionally narrow. If a command needs something outside it, first ask whether the command is reaching below the correct abstraction.
Autonomous and teleop navigation split¶
Autonomous and teleop navigation use different tools:
- BLine loads committed JSON paths for autonomous.
- PathPlanner performs runtime
pathfindToPosefor teleop navigation.
Do not use PathPlanner-authored autos in this template. Do not use BLine for teleop navigation. Keeping the split makes failures easier to diagnose and keeps the autonomous workflow stable.
Logging is part of the architecture¶
AdvantageKit is not an add-on dashboard helper. It is the record of what the robot thought happened.
Use:
Logger.processInputs(...)for IO input structs.Logger.recordOutput(...)for derived values, command state, selected auto, navigation state, and dashboard aliases.LoggedDashboardChooserfor autonomous selection.
Do not create direct NetworkTables publishers for normal telemetry. The configured AdvantageKit NT4 publisher exposes logged outputs to dashboards while preserving replay and log consistency.