Project 1: A Production-Ready Driver Control Scheme
A control scheme is doing its job when the driver stops noticing it. They think “go there” and the robot goes there. The scheme below is WPILib command-based Java, written for an actual competition driver.
Start in RobotContainer with a CommandXboxController on port 0. WPILib gives you named factory methods for every button, so you bind declaratively instead of polling in a loop.
private final CommandXboxController driver = new CommandXboxController(0);private final DriveSubsystem drive = new DriveSubsystem();
private void configureBindings() { // Default command: field-relative joystick drive every loop drive.setDefaultCommand(drive.run(() -> drive.driveFieldRelative( -driver.getLeftY(), // forward (Y is inverted on Xbox sticks) -driver.getLeftX(), // strafe -driver.getRightX() // rotation )));
// Reset field-relative heading to "away from driver station" driver.start().onTrue(drive.runOnce(drive::zeroHeading));
// Hold left bumper for precision/slow mode driver.leftBumper().whileTrue(drive.run(() -> drive.driveFieldRelative( -driver.getLeftY() * 0.35, -driver.getLeftX() * 0.35, -driver.getRightX() * 0.35)));}Those minus signs matter. Xbox sticks report +1 when pulled toward the driver, so forward needs a negative sign, and forgetting it is the single most common day-one bug.
onTrue and whileTrue are the two binding methods you will use most. onTrue runs once on a rising edge, which is what a gyro reset needs. whileTrue runs while the button is held and cancels on release, which is what slow mode needs.
Slow mode here is a scale factor rather than a separate command tree. Multiplying the inputs by 0.35 gives about one-third speed for lining up on the HUB or playing careful defense, and you don’t have to duplicate any logic.
Apply a deadband so a drifting stick doesn’t creep the robot. MathUtil.applyDeadband(value, 0.1) is the idiomatic call. The DifferentialDrive class already applies 0.02 internally, but in swerve code you apply your own, and 0.05 to 0.10 is typical.
double x = MathUtil.applyDeadband(-driver.getLeftX(), 0.1);Write the physical mapping down and tape it to the operator console: Left stick = translate, Right stick = rotate, Start = reset gyro, Left bumper = slow. Hand that card to a substitute driver and they should be able to drive a qualification match cold.
Test it on blocks first, then on the practice field. Drive a figure-eight around two cones. If the robot tracks where you point in field-relative mode no matter which way the bumper is facing, your gyro and inversions are correct.
Key takeaways
Section titled “Key takeaways”- Use CommandXboxController factory methods (start(), leftBumper()) with onTrue for one-shot actions and whileTrue for held actions.
- Invert Xbox Y axes for forward, and apply your own deadband (0.05-0.10) on swerve before scaling for slow mode.
- Document the physical button map on a card at the operator console so any driver can run a match.
This lesson was adapted from learnfrc.com.
