This is a modified version of the CTRE Generated Swerve Code, enhanced with Maple-Sim for better simulation capabilities.
This integration enables a realistic physics-based simulation using Maple-Sim with CTRE Swerve. You can fine-tune autonomous modes, optimize subsystems, and test advanced interactions in a simulated environment.
To integrate Maple-Sim with new CTRE swerve projects:
- Generate the
TunerConstants.java
file using Phoenix Tuner X. - Place the generated file in your project at
generated/TunerConstants.java
. - Deploy the code to your robot!
For existing CTRE swerve projects, follow these steps to integrate the simulation:
Ensure your project was generated using Phoenix Tuner X 2025.2.0.0+
.
Install the latest version of Maple-Sim. Refer to the installation guide for detailed instructions.
Download this source file and place it in the src/main/java/frc/robot/utils/simulation
directory of your project.
Update your subsystems/CommandSwerveDrivetrain.java
file as follows:
-
Change the Simulation Implementation Replace the existing
startSimThread
method with the code below:private MapleSimSwerveDrivetrain mapleSimSwerveDrivetrain = null; private void startSimThread() { mapleSimSwerveDrivetrain = new MapleSimSwerveDrivetrain( Seconds.of(kSimLoopPeriod), // TODO: modify the following constants according to your robot Pounds.of(115), // robot weight Inches.of(30), // bumper length Inches.of(30), // bumper width DCMotor.getKrakenX60(1), // drive motor type DCMotor.getFalcon500(1), // steer motor type 1.2, // wheel COF getModuleLocations(), getPigeon2(), getModules(), TunerConstants.FrontLeft, TunerConstants.FrontRight, TunerConstants.BackLeft, TunerConstants.BackRight); /* Run simulation at a faster rate so PID gains behave more reasonably */ m_simNotifier = new Notifier(mapleSimSwerveDrivetrain::update); m_simNotifier.startPeriodic(kSimLoopPeriod); }
-
Regulate the Module Constants Modify the constructor to regulate the module constants. Note: This will modify your module constants during simulation to avoid known bugs during, skips if running on a real robot.
/** ... */ public CommandSwerveDrivetrain( SwerveDrivetrainConstants drivetrainConstants, double odometryUpdateFrequency, SwerveModuleConstants<?, ?, ?>... modules) { super( drivetrainConstants, odometryUpdateFrequency, // modules MapleSimSwerveDrivetrain.regulateModuleConstantsForSimulation(modules)); if (Utils.isSimulation()) { startSimThread(); } configureAutoBuilder(); } /** ... */ public CommandSwerveDrivetrain( SwerveDrivetrainConstants drivetrainConstants, double odometryUpdateFrequency, Matrix<N3, N1> odometryStandardDeviation, Matrix<N3, N1> visionStandardDeviation, SwerveModuleConstants<?, ?, ?>... modules) { super( drivetrainConstants, odometryUpdateFrequency, odometryStandardDeviation, visionStandardDeviation, // modules MapleSimSwerveDrivetrain.regulateModuleConstantsForSimulation(modules)); if (Utils.isSimulation()) { startSimThread(); } configureAutoBuilder(); }
-
Reset the Robot Simulation Pose Update the resetPose method to sync simulation and real-world poses:
@Override public void resetPose(Pose2d pose) { if (this.mapleSimSwerveDrivetrain != null) mapleSimSwerveDrivetrain.mapleSimDrive.setSimulationWorldPose(pose); Timer.delay(0.05); // Wait for simulation to update super.resetPose(pose); }