Class RobotBumpSim
What this class does
Simulates the robot's 3D pose (Z height, pitch, and roll) as it drives over the raised bumps on the 2026 FRC REBUILT field. It also implements a frictionless-slide model that prevents the robot from "ghosting" through a bump when it lacks the speed to crest it.
How it works
- Four swerve module contact points are tracked independently in the XZ plane.
- When any module first touches a bump's ascending face the sim enters ramp mode: it
captures the robot's current field-X velocity (
simXVel) and absolute field-X position (simXPos), then owns them for the duration of the crossing attempt. - While on the ramp, only gravity acts along X (frictionless surface). If
simXVeldecays to zero before the peak the robot slides back to flat ground. - The robot exits ramp mode when it either backs off (all module Z ≈ 0) or successfully crosses over the peak (modules come back to flat ground on the far side).
- A diagonal approach reduces effective deceleration via
contactFactor = |cos(2 * robotYaw)|, making 45° crossings easier.
Minimum crossing speed: sqrt(2·g·h) ≈ sqrt(2·9.81·0.165) ≈ 1.80 m/s.
Quick-start integration with MapleSim
// 1. Construct once, typically in startSimThread() alongside your MapleSim drivetrain.
RobotBumpSim robotBumpSim = new RobotBumpSim(drivetrain.getModuleLocations());
// 2. Call every simulationPeriodic() AFTER MapleSim has stepped.
Pose2d simPose = mapleSimDrive.getSimulatedDriveTrainPose();
ChassisSpeeds fieldRelativeSpeeds = mapleSimSwerveDrivetrain.mapleSimDrive.getDriveTrainSimulatedChassisSpeedsFieldRelative();
// subticks should match the number of physics sub-steps you pass to your ball/object sim.
// A value of 5 works well for a 20 ms loop (4 ms sub-steps).
Pose3d simPose3d = robotBumpSim.update(simPose, fieldSpeeds, subticks);
// 3. When on the ramp, override MapleSim's pose so the robot physically slides back
// instead of the correction being purely visual.
if (robotBumpSim.isOnRamp()) {
mapleSimDrive.setSimulationWorldPose(robotBumpSim.getSimWorldPose(simPose));
}
// 4. Log or visualise the 3D pose (e.g. with AdvantageScope).
Logger.recordOutput("Drive/Pose3d", simPose3d);
Tunable constants
WHEEL_RADIUS— effective contact radius of a wheel against the ramp surface (metres). Increase this to make the robot appear to "float" higher above the bump.CHASSIS_HEIGHT— offset from the average module-contact Z to the robot body origin. Set to your chassis clearance height if you want a visually accurate robot body Z.BUMP_COR— coefficient of restitution for vertical collisions with the bump. 0 = perfectly inelastic (no bounce), 1 = perfectly elastic.
Field geometry
The bump geometry is encoded as XZ line segments with Y-range guards. Each bump has two
segments per side (ascending face + descending face) at X positions symmetric about field centre.
See BUMP_LINE_STARTS / BUMP_LINE_ENDS for the raw coordinates. All positions
are in metres, origin at the Blue Alliance driver-station corner.
-
Constructor Summary
ConstructorsConstructorDescriptionRobotBumpSim(Translation2d[] moduleOffsets) Creates a newRobotBumpSimfor a swerve drivetrain. -
Method Summary
Modifier and TypeMethodDescriptiongetSimWorldPose(Pose2d latestMaplePose) Returns the 2D pose that should be set on MapleSim while on the ramp.booleanisOnRamp()Returnstruewhile the robot is on the ramp in frictionless-slide mode.update(Pose2d robotPose2d, ChassisSpeeds fieldRelativeSpeeds, int subticks) Advances the bump simulation by one 20 ms period and returns the robot's 3D pose.
-
Constructor Details
-
RobotBumpSim
Creates a newRobotBumpSimfor a swerve drivetrain.- Parameters:
moduleOffsets- Robot-relative module positions in order FL, FR, BL, BR (metres). Typically obtained viaCommandSwerveDrivetrain#getModuleLocations().
-
-
Method Details
-
isOnRamp
public boolean isOnRamp()Returnstruewhile the robot is on the ramp in frictionless-slide mode.When
truethe caller must callgetSimWorldPose(Pose2d)to obtain the corrected 2D pose and feed it to MapleSim viasetSimulationWorldPose, so the robot actually slides backward rather than just appearing to. -
getSimWorldPose
Returns the 2D pose that should be set on MapleSim while on the ramp.The X coordinate is replaced with the frictionless
simXPos; Y and rotation are taken fromlatestMaplePoseso MapleSim continues to own lateral motion.- Parameters:
latestMaplePose- The most recent 2D pose read from MapleSim (used for Y and rotation).- Returns:
- A corrected
Pose2dto pass tosetSimulationWorldPose.
-
update
Advances the bump simulation by one 20 ms period and returns the robot's 3D pose.When the robot is on the ramp the returned pose uses
simXPosfor X, giving a physically accurate visual position. The caller must also callgetSimWorldPose(Pose2d)and apply it to MapleSim so the actual simulation position matches (see the class-level Javadoc for a complete integration example).- Parameters:
robotPose2d- Robot's 2D pose from the MapleSim drivetrain.fieldRelativeSpeeds- Field-relative chassis speeds from the MapleSim drivetrain.subticks- Physics sub-steps per period. Must match thesubticksvalue used by any companion ball/object sim so they stay in sync. Typical value: 5 (= 4 ms sub-steps per 20 ms loop).- Returns:
- A
Pose3dwith physically correct X, Z, pitch, and roll.
-