Coding Standards
MARSLib follows strict coding standards to maintain consistency, safety, and performance. These standards ensure our code is readable, maintainable, and reliable for FRC competition use.
Core Principles
Section titled “Core Principles”🎯 Zero-Allocation
Section titled “🎯 Zero-Allocation”Avoid memory allocations in time-critical code paths (100Hz+ loops).
❌ Avoid:
@Overridepublic void periodic() { // BAD: Creates new object every 20ms Pose2d pose = new Pose2d(x, y, new Rotation2d(theta));}// Reuse objectsprivate final Pose2d pose = new Pose2d();
@Overridepublic void periodic() { pose.setX(x); pose.setY(y); pose.getRotation().setTheta(theta);}Warning: Mathematical Mutation
Do not pass structural pointers to objects that must preserve historic state (e.g. PID integrators). Always use.clone()if a downstream pipeline requires an immutable snapshot of an Ephemeral Struct.
🔒 Thread Safety
Section titled “🔒 Thread Safety”All shared state must be thread-safe. Use volatile for primitives, concurrent collections, or synchronized blocks.
❌ Avoid:
private double sharedValue; // BAD: Not thread-safe
public void setValue(double v) { sharedValue = v; // Race condition!}✅ Preferred:
private volatile double sharedValue; // Thread-safe primitive
// Or use atomic typesprivate final AtomicDouble sharedValue = new AtomicDouble();🧪 Testability
Section titled “🧪 Testability”Write code that’s easily testable with simulated IO.
// Interface-based design enables testingpublic class MechanismSubsystem extends Subsystem { private final MechanismIO io; // Can be real or simulated
// Same code works on robot and in simulation!}Code Style
Section titled “Code Style”Formatting
Section titled “Formatting”We use Spotless for automatic formatting. Don’t manually format code.
# Apply Spotless formatting.\gradlew.bat spotlessApply
# Check formatting.\gradlew.bat spotlessCheckNaming Conventions
Section titled “Naming Conventions”Classes: PascalCase
public class SwerveDrive {}public class MARSVision {}Methods: camelCase
public void driveRobotRelative() {}public void updateOdometry() {}Constants: UPPER_SNAKE_CASE
private static final double MAX_SPEED_MPS = 5.0;private static final double LOOP_PERIOD_SECS = 0.02;Private Fields: camelCase with this prefix
private final SwerveDrive drive;private final VisionIO vision;🚫 Banned: Hungarian Notation
Section titled “🚫 Banned: Hungarian Notation”Using m_ prefixes to dictate member variables is an archaic C++ practice that poisons Java IDE autocompletion and drastically reduces readability. MARSLib strictly bans Hungarian notation. We rely on modern syntax highlighting and the this. keyword for variable scope.
❌ Avoid:
private final SwerveDrive m_swerve;private double m_speed;
public void setSpeed(double speed) { m_speed = speed;}✅ Preferred:
private final SwerveDrive swerve;private double targetVelocity;
public void setVelocity(double targetVelocity) { this.targetVelocity = targetVelocity;}📏 Explicit Unit Nomenclature
Section titled “📏 Explicit Unit Nomenclature”A double named speed has destroyed billions of dollars in real-world aerospace missions through misunderstanding units. Passing raw sensor ticks or ambiguous integers into high-level functions is banned. Variables must describe precisely what they represent.
❌ Avoid:
// What is 'tolerance'? Degrees? Radians?// What is 'speed'? RPM? M/s? Volts?public void setAngle(double angle, double tolerance) { ... }public void runIntake(double speed) { ... }✅ Preferred:
// Mathematically explicit parameterspublic void setAngle(double radians, double toleranceRads) { ... }public void runIntake(double voltageOut) { ... }🚫 The “Never Nester” Protocol
Section titled “🚫 The “Never Nester” Protocol”Code that is deeply nested across multiple if/else and for blocks is fragile and requires immense cognitive load to debug under competition pressure. All FRC control loops must remain completely “flat”. use guard clauses and early return expressions immediately.
❌ Avoid:
public void shoot() { if (systemReady) { if (targetLocked) { if (flywheelAtSpeed) { feeder.run(); } } }}✅ Preferred:
public void shoot() { if (!systemReady) return; if (!targetLocked) return; if (!flywheelAtSpeed) return;
feeder.run();}structure Patterns
Section titled “structure Patterns”IO Abstraction Layer
Section titled “IO Abstraction Layer”Separate logic from hardware using interfaces.
// Define the interfacepublic interface MechanismIO { double getPosition(); void setVoltage(double voltage);}
// Hardware implementationpublic class MechanismIOReal implements MechanismIO { private final TalonFX motor;
public double getPosition() { return motor.getPosition().getValueAsDouble(); }}
// Simulated implementationpublic class MechanismIOSim implements MechanismIO { private double position = 0.0;
public double getPosition() { return position; }}Command-Based Programming
Section titled “Command-Based Programming”Use WPILib’s Command-based pattern for all robot actions.
public class DriveCommand extends Command { private final SwerveDrive drive;
public DriveCommand(SwerveDrive drive) { this.drive = drive; addRequirements(drive); // Always declare requirements }
@Override public void execute() { // Control logic }}Subsystem Design
Section titled “Subsystem Design”Subsystems should manage IO and state, not implement business logic.
public class ElevatorSubsystem extends Subsystem { private final LinearMechanismIO io; private final PIDController controller;
@Override public void periodic() { // Update control loops double output = controller.calculate(io.getPosition()); io.setVoltage(output); }
// Public API for commands public void setPosition(double meters) { controller.setSetpoint(meters); }}Performance Standards
Section titled “Performance Standards”Loop Timing
Section titled “Loop Timing”- Teleop Periodic: 50Hz (20ms)
- Auto Periodic: 50Hz (20ms)
- Odometry: 250Hz (4ms)
- Vision Processing: As fast as possible (30Hz+)
Memory Management
Section titled “Memory Management”- Pre-allocate all objects in constructor.
- Avoid object creation in periodic() methods.
- Use object pools for temporary objects.
Logging
Section titled “Logging”- Use AdvantageKit automatic logging.
- Don’t manually log in time-critical loops.
- Log at appropriate levels (ERROR, WARN, INFO)
Safety Standards
Section titled “Safety Standards”Hardware Safety
Section titled “Hardware Safety”public class SafeSubsystem extends Subsystem { @Override public void periodic() { // Check limits if (getPosition() > MAX_POSITION) { stop(); // Emergency stop MARSFaultManager.fault("Position limit exceeded!"); } }}Fault Handling
Section titled “Fault Handling”public class RobustSubsystem extends Subsystem { private final VisionIO vision;
@Override public void periodic() { try { var pose = vision.getPoseEstimate(); if (pose.isPresent()) { // Use vision data } else { // Handle missing data gracefully MARSFaultManager.warn("Vision estimate unavailable"); } } catch (Exception e) { MARSFaultManager.fault("Vision error: " + e.getMessage()); } }}State Management
Section titled “State Management”public class SafeStateMachine extends MARSStateMachine<State> { public SafeStateMachine() { super("Safe", State.IDLE);
// Always include emergency stop state addState(State.ESTOP, () -> { // Stop all motion drive.stop(); shooter.stop(); elevator.holdPosition(); }); }}Testing Standards
Section titled “Testing Standards”Digital Twin Philosophy
Section titled “Digital Twin Philosophy”Test with real subsystems using simulated IO.
@Testpublic void testSwerveOdometry() { MARSTestHarness.reset();
// Use real subsystem with simulated IO SwerveDrive drive = new SwerveDrive(new SwerveModuleIOSim());
// Run physics simulation for (int i = 0; i < 150; i++) { DriverStationSim.notifyNewData(); SimHooks.stepTiming(0.02); CommandScheduler.getInstance().run(); }
// Verify results assertEquals(finalPose, drive.getPose());}Test Coverage
Section titled “Test Coverage”- Maintain 80%+ test coverage.
- Test both success and failure cases.
- Use realistic physics in tests.
Documentation Standards
Section titled “Documentation Standards”JavaDoc
Section titled “JavaDoc”Document all public APIs:
/** * Swerve drive subsystem with odometry and path following. * * <p>This subsystem manages four swerve modules with independent * wheel angle and velocity control. Odometry is updated at 250Hz * using a dedicated thread. * * @param modules Array of four swerve modules * @param config Swerve drive configuration parameters */public class SwerveDrive extends Subsystem { // ...}Code Comments
Section titled “Code Comments”- Comment why, not what.
- Explain non-obvious algorithms.
- Document performance-critical sections.
- Keep comments up-to-date.
Common Patterns
Section titled “Common Patterns”PID Control
Section titled “PID Control”public class PIDSubsystem extends Subsystem { private final ProfiledPIDController controller; private final MechanismIO io;
public PIDSubsystem() { // Use ProfiledPID for smooth motion controller = new ProfiledPIDController( 8.0, 0.0, 0.15, // Gains from SysId new TrapezoidProfile.Constraints(2.0, 4.0) ); }
@Override public void periodic() { double output = controller.calculate(io.getPosition()); io.setVoltage(output + calculateFeedforward()); }}State Machines
Section titled “State Machines”public class StateMachineExample extends MARSStateMachine<State> { public StateMachineExample() { super("Example", State.IDLE);
addState(State.IDLE, () -> { // Stop all motion });
addState(State.RUNNING, () -> { // Run mechanism }); }}Vision Integration
Section titled “Vision Integration”public class VisionAlignment extends Command { private final MARSVision vision;
@Override public void execute() { var pose = vision.getPoseEstimate(); if (pose.isPresent()) { // Use vision data alignToPose(pose.get()); } else { // Handle missing data MARSFaultManager.warn("No vision target"); } }}Code Review Checklist
Section titled “Code Review Checklist”Before submitting code, verify:
- Code follows naming conventions.
- No allocations in periodic() methods.
- Thread-safe shared state.
- Proper error handling.
- Tests added and passing.
- Documentation updated.
- Spotless formatting applied.
- Performance tested (if applicable)
Tools and Automation
Section titled “Tools and Automation”Pre-commit Hooks
Section titled “Pre-commit Hooks”Install git hooks for automatic formatting:
.\install-git-hooks.batCI/CD Checks
Section titled “CI/CD Checks”Our CI automatically verifies:
- Spotless formatting.
- 80% test coverage.
- All tests pass.
- No compilation errors.
VS Code Extensions
Section titled “VS Code Extensions”- Extension Pack for Java - Language support.
- Gradle for Java - Build integration.
- Spotless - Format on save.
Next: Learn about our Testing Guide to understand the Digital Twin philosophy!