This is a Kotlin WPILib robot project built around AdvantageKit for deterministic logging + replay. It currently includes a Phoenix 6 TalonFX-integrated swerve drive, vision pose fusion (PhotonVision/Limelight IO), SmartField field-object tracking (optional), and a small LED “mode” subsystem coordinated by a simple Superstructure.
- Drive (swerve): odometry + pose estimation + SysId/characterization + Choreo trajectory following
- Real IO: TalonFX integrated modules + Pigeon2 gyro (
GyroIOPigeon2) - Sim IO:
ModuleIOSim+ no-op gyro (stub)
- Real IO: TalonFX integrated modules + Pigeon2 gyro (
- Vision: consumes camera pipelines, filters pose observations, and forwards accepted measurements into the drive pose estimator
- IO options exist for PhotonVision and Limelight (pick one in
RobotContainer)
- IO options exist for PhotonVision and Limelight (pick one in
- SmartField (optional): fuses “detections” into tracked field objects with short-term memory + visibility diagnostics
- Subsystem + IO implementations exist, but it is not constructed by default in
RobotContainer
- Subsystem + IO implementations exist, but it is not constructed by default in
- LEDs: abstracted IO (native) with a small state machine (OFF / DISABLED / AUTO / TELEOP)
- Autos: Choreo
AutoFactory+ an Auto DSL for readable command composition and runtime branching - Utilities: Kotlin DSL helpers for commands/units/triggers, plus small robot helpers (alliance flipping, Autopilot proxy, Phoenix utils)
- Internal libraries: reusable code under
src/main/kotlin/frc/lib/*(currentlyfrc.lib.smartfield)
- Entry points / composition
src/main/kotlin/frc/robot/Main.kt: JVM entrypoint (intentionally boring)src/main/kotlin/frc/robot/Robot.kt: AdvantageKit logger setup (REAL/SIM/REPLAY) + scheduler loopsrc/main/kotlin/frc/robot/RobotContainer.kt: composition root (subsystems + IO selection + bindings + auto chooser)
- Docs
- DSL guide:
docs/DSL.md - Autos guide (full):
docs/Autos.md
- DSL guide:
- Subsystems
src/main/kotlin/frc/robot/subsystems/drive/Drive.kt: swerve odometry + control surface used by commands/autossrc/main/kotlin/frc/robot/subsystems/vision/Vision.kt: pose filtering + std-dev model + measurement forwardingsrc/main/kotlin/frc/robot/subsystems/smartfield/SmartField.kt: tracked field objects fusionsrc/main/kotlin/frc/robot/subsystems/leds/Leds.kt: LED state + IO abstraction
- Commands / autos
src/main/kotlin/frc/robot/commands/DriveCommands.kt: drive command factories (joystick drive, SysId helpers, go-to-pose via Autopilot)src/main/kotlin/frc/robot/Autos.kt: Choreo routines and dashboard chooser wiringsrc/main/kotlin/frc/robot/util/dsl/AutoDSL.kt: the Auto DSL used by autos
src/main/kotlin/frc/robot/
Robot.kt # AdvantageKit init + lifecycle
RobotContainer.kt # Subsystems, IO implementations, bindings, auto chooser
Autos.kt # Choreo autos + SysId auto
Superstructure.kt # Robot-wide “goal/mode” coordinator (currently mainly LEDs)
subsystems/
drive/ # Swerve drive subsystem + IO implementations
vision/ # Vision fusion + IO implementations (PhotonVision/Limelight)
smartfield/ # Field object tracking + IO layer
leds/ # LED subsystem + IO layer
commands/
DriveCommands.kt # Command factories (no Command subclasses)
util/
dsl/ # Command/trigger/unit helpers + Auto DSL
* # Misc utilities (AllianceFlipUtil, AutopilotProxy, PhoenixUtil, ...)
generated/
TunerConstants.kt # CTRE-generated swerve constants (do not hand-edit)
src/main/deploy/ # Files deployed to roboRIO (/home/lvuser/deploy)
choreo/ # Choreo `.traj` files (used for autos + codegen)
vendordeps/ # AdvantageKit, Phoenix6, PhotonLib, Choreo, etc.
This project generates type-safe Kotlin sources from src/main/deploy/choreo/*.traj:
- Generated enums:
frc.robot.generated.ChoreoPath(typed path names) - Generated typed markers:
frc.robot.generated.ChoreoTraj(path-scoped marker constants with optional timestamps) - Where it lives:
build/generated/sources/choreo/kotlin/frc/robot/generated/*(do not edit) - How it’s generated: Gradle task
generateChoreoPaths(runs automatically beforecompileKotlin)
Mode selection is centralized in src/main/kotlin/frc/robot/Constants.kt:
- REAL: logs to USB (
/U/logs) and publishes to NT4 - SIM: logs to NT4 (optionally enables vision sim via
Constants.VISION_SIM_ENABLED) - REPLAY: reads the latest log and writes a
_simreplay log (runs “as fast as possible”)
Run these from the repo root:
- Build:
./gradlew build - Run tests:
./gradlew test - Format:
./gradlew spotlessApply(enforced viaspotlessinbuild.gradle) - Sim (desktop):
./gradlew simulateJava - Deploy to roboRIO:
./gradlew deploy - AdvantageKit replay viewer:
./gradlew replayWatch
Notes:
- The robot main class is
frc.robot.Main(seebuild.gradle). - On real hardware, AdvantageKit logs go to the roboRIO USB path
/U/logs.
- IO-layer subsystems: subsystems read hardware only through
*IOinterfaces and log inputs via AdvantageKit. - Deterministic replay: timebase uses
Timer.getTimestamp()(not FPGA timestamp) and avoids hidden external state. - Command factories: commands are composed via factory methods (e.g.
DriveCommands) instead of subclassingCommand. - Superstructure coordination: robot-wide “intent” lives in
Superstructure(so subsystems don’t call each other directly).
This codebase uses a few small Kotlin DSL/helper layers to keep robot code readable while staying compatible with AdvantageKit replay (i.e., avoiding “decide at robot init” bugs).
-
Auto DSL (
src/main/kotlin/frc/robot/util/dsl/AutoDSL.kt)- Used in
Autos.ktto author autos as readable blocks that compile down to normal WPILib commands. - Provides helpers like
follow("Path"),follow("Path") { atEvent("Marker") { ... } },parallel { ... },wait(1.0),goToPose(pose), and runtime branching. - Important behavior: pose helpers apply alliance flipping (author once, run on red/blue).
- Determinism feature: pose-driving uses
Commands.defer { ... }so the command is built at schedule time.
- Used in
-
WPILib Command DSL (
src/main/kotlin/frc/robot/util/dsl/WpilibDsl.kt)- General-purpose command composition DSL:
command { ... }withsequence/parallel/race/deadline. - Schedule-time branching helpers:
defer { ... }: build a command when it schedules (avoid stale sensor/chooser values).either(...)/eitherDefer(...)/select(...): readable runtime branching (with safer schedule-time construction available).
- Trigger helpers so bindings can stay declarative:
Trigger.onTrue { ... },whileTrue { ... }, etc.
- General-purpose command composition DSL:
-
Units + Optional helpers
src/main/kotlin/frc/robot/util/dsl/UnitsDsl.kt: short, typed unit literals like1.0.m,20.deg,8.5.mps2.src/main/kotlin/frc/robot/util/dsl/OptionalDsl.kt: converts JavaOptional/OptionalDoubleto Kotlin-nullables viaorNull().
follow(ChoreoTraj.DRIVE_TO_REEF, resetOdometry = true) {
atEvent(ChoreoTraj.DRIVE_TO_REEF.ELEV_HALF_UP) { print("marker fired") }
beforeEnd(0.25.s) { print("prep") }
}drive.defaultCommand =
DriveCommands.joystickDrive(
drive,
{ -controller.leftY },
{ -controller.leftX },
{ -controller.rightX },
linearAccelLimit = 8.5.mps2,
angularAccelLimit = 10.0.rps2,
)From vendordeps/ and code usage:
- WPILib (2026) + Command-based
- AdvantageKit (logging + replay)
- CTRE Phoenix 6 (swerve modules / TalonFX integrated)
- PhotonVision (vision IO) and a Limelight IO implementation
- Choreo (autonomous trajectories)
- Autopilot (pose-to-pose driving helper, wrapped via
AutopilotProxy)
