Skip to content

Task/2025 refactor - #27

Draft
robotdirtbag wants to merge 24 commits into
mainfrom
task/2025-refactor
Draft

Task/2025 refactor#27
robotdirtbag wants to merge 24 commits into
mainfrom
task/2025-refactor

Conversation

@robotdirtbag

@robotdirtbag robotdirtbag commented Sep 22, 2025

Copy link
Copy Markdown
Collaborator

Refactor: simulation-ready swerve, input plumbing, motor abstraction, and package re-org

What changed (high-level)

  • Simulation & swerve drivetrain
    • Added a viable simulated drivetrain with SwerveModuleSim, proper voltage scaling, and faster azimuth response for crisp direction changes.
    • Reworked Drivetrain and SwerveModule under frc.robot.subsystems.drivetrain/* with context objects for tunables and dependency injection.
    • Fixed sim stability by ensuring one source of odometry/pose update per loop; sim now integrates module states + simulated yaw consistently.
    • Introduced clearer constants (e.g., sim turn-voltage gains) and unit-explicit names.
  • Controls & commands
    • Split SwerveDriveCommand into commands/swervedrive/* and added a ControllerDelegate to map DS axes/inputs cleanly (works with Sim GUI keyboard).
    • Consolidated PID commands (e.g., AlgaePIDCommand, ElevatorPIDCommand) and removed legacy variants.
  • Subsystems re-org
    • Moved mechanisms into dedicated packages with *Context classes: algae/*, coral/*, climb/*, elevator/*, vision/*. Removed deprecated top-level variants.
  • Motor abstraction
    • Introduced TeamSparkMax, with TeamSparkMaxImpl (real) and TeamSparkMaxSimImpl (sim) to keep vendor wiring out of subsystems.
    • Sim safety: In sim, closed-loop feedback defaults to primary encoder to avoid REV data-port/alt-encoder mode conflicts; real robot still uses alt/external encoder when configured.
  • Build & formatting
    • Switched to Palantir Spotless and cleaned up formatting; simplified Robot lifecycle boilerplate.
    • Integrated JaCoCo test coverage and associated reports. Our GitHub will retain our coverage reports in xml and html formats to support review.
    • Required coverage percentage is intentionally low (0.03) since historically we have had no test coverage. As coverage increases, so will our required coverage percentage.
    • Added .gitattributes file to ensure consistent line endings across Windows, Mac, and Linux development environments

Notable implementation details

  • Swerve simulation
    • SwerveModuleState.optimize() is applied against current module angle before computing volts, ensuring shortest-path steering with correct speed sign flips.
    • Increased sim steering P gain (commit history shows multiple bumps) so modules re-aim quickly; reduces “arcing” when switching F/B ↔ L/R.
    • Explicit volts-per-m/s scaling and clamping to ±bus voltage for realistic drive behavior.
  • Odometry & pose
    • Central getHeading() + getSwerveModulePositions() switch between sim and real sources; pose estimator updated exactly once per loop.
    • Sim resets to a known pose on mode enable to prevent drift across enables.
  • Input path
    • In sim, controller suppliers read DriverStation axes so Sim GUI keyboard maps cleanly; deadband/sign are handled in the command.

Files touched (selected)

  • New/major: subsystems/drivetrain/Drivetrain.java, SwerveModule.java, DrivetrainContext.java, SwerveModuleContext.java, sim/SwerveModuleSim.java, commands/swervedrive/*, support/sparkmax/*.
  • Removed/renamed: legacy DriveTrain.java, older mechanism files, and several legacy commands replaced by namespaced versions.

Behavior improvements

  • Pure strafe no longer “rockets” off-axis; field-relative motion matches expectations in sim.
  • Direction changes produce minimal curvature thanks to faster azimuth and optimized module commands.
  • Sim starts from zeroed pose; repeated enables don’t accumulate heading/pose error.

Risks / compatibility

  • Mechanism classes moved; external code must import from new packages.
  • If alternate encoder closed-loop is required in sim, additional sim configuration for REV data-port would be needed (real hardware unaffected).

How I tested

  • Keyboard A/D and W/S produce expected x/y speeds; logs show correct chassis speeds and module angles for pure translation.
  • Verified single odometry/estimator update per loop in sim via log traces.
  • Smoke tests and telemetry tests still pass with minor updates.
  • New SwerveDriveCommandTest demonstrates use of Mockito-based mocks for testing SwerveDriveCommand#execute logic

Follow-ups

  • Optional: cosine-scale drive speed by azimuth error in SwerveModule.setDesiredState() for even sharper direction snaps.
  • Add explicit CPR constant for climb alt encoder (if not already defined) and document data-port mode in the context.
  • (If desired) simulate vision latency before re-enabling vision fusion in sim.

Note that these changes were validated on macOS and due to strangeness with HID drivers - so sim validation was performed using keyboard joystick. Reviews should also be done on Windows w/XBox style controllers.

keyboard_sim

field_sim

@robotdirtbag robotdirtbag self-assigned this Sep 22, 2025
smonaghanx and others added 4 commits October 4, 2025 22:46
…age in sim results in a tighter turn when changing driving direction. additional variable naming factor and constants
…onstant again for tighter turns in sim. Bypass crash when running ClimbMechanism in sim by using ClosedLoopConfig.FeedbackSensor.kPrimaryEncoder
@robotdirtbag

Copy link
Copy Markdown
Collaborator Author

@FumperForrest These are the changes I made as part of a codebase refactor. I'm submitting this as a draft, so let's not merge until we've had a chance to discuss and deploy to the robot to see what broke.

I primarily focused on restructuring the subsystems, organizing them into packages, capturing hard-coded values into documented fields and removing dead code. As for the subsystems I introduced the concept of a "context" - where each subsystem accepts an associated "context" object that maintains its properties. I favor that over hard coding the values inline within each subsystem. My hope is that if we establish this pattern going forward, we'll promote a clean separation between the configuration state and the subsystem logic. Also by doing this, we're a step closer to something like a json-based configuration, where we maintain all of these "magic values" within simple json files, making it easier to tweak and track changes. For the context classes I used Lombok and its builders for keeping things clean. We can talk more about that later, but in short each context has a public static "defaults" method which returns an instance of the context with all values set to their original 2025 values - the intention being that when we deploy the refactor, things should behave as they did last year.

And for the 2026 subsystems, we can continue to use this pattern... for each new subsystem, we create an associated context.

@robotdirtbag
robotdirtbag force-pushed the task/2025-refactor branch 2 times, most recently from f9723d0 to 5727c45 Compare October 5, 2025 23:39
@robotdirtbag
robotdirtbag force-pushed the task/2025-refactor branch 2 times, most recently from 1bf5ddf to eb5f3d7 Compare October 6, 2025 02:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants