From button to action in command-based WPILib
In modern WPILib, you bind controls to robot behavior declaratively using Trigger objects, typically in RobotContainer. The recommended class is CommandXboxController. You create it on a port (matching the USB order), then bind its buttons to commands:
// Driver controller on port 0
CommandXboxController driver = new CommandXboxController(0);
// Run the intake while the right bumper is held
driver.rightBumper().whileTrue(intake.runIntakeCommand());
// Score once when A is pressed
driver.a().onTrue(scoreCommand());
The library automatically polls these triggers and schedules the right command — you declare the mapping once at startup.
The binding methods
Per the WPILib Binding Commands to Triggers docs, each Trigger offers these methods:
onTrue(command)— schedules the command once when the trigger goes fromfalsetotrue; it won't run again until the trigger goes false and true again. Good for discrete actions ("shoot," "go to a position").onFalseis the same on release.whileTrue(command)— schedules the command when the trigger becomestrueand cancels it when the trigger becomesfalse. Good for "run intake while I hold this" or "hold to aim."whileFalseis the mirror.toggleOnTrue(command)— toggles the command on with one press and off with the next. The docs explicitly say toggles are not a highly-recommended option for user control because they require the driver to track robot state; the preferred approach is two buttons (one to turn on, one to turn off).
You can also use the POV/d-pad (driver.povUp()), treat an analog trigger or stick axis as a button with a threshold (e.g., driver.rightTrigger(0.5)), and compose triggers with .and() / .or() and .debounce() to filter noise.
Designing the control scheme
Good mappings are designed for humans under stress, not for code convenience:
- Split by role: drivetrain on the driver's thumbsticks; mechanisms on the operator's controller or button board.
- Group related actions physically (all scoring buttons together) and keep dangerous actions (like a climber release) guarded — require a second button, or place it where it can't be hit accidentally.
- Prefer hold-to-run for transient actions (
whileTrue) so releasing instantly stops the mechanism — a built-in safety. - Keep it consistent across the season; rebinding the week before champs forces the driver to relearn muscle memory.
Find your button numbers fast
When a control isn't doing what you expect, the USB Devices tab shows live button and axis values so you can press a physical button and see exactly which index lights up. Some teams write a tiny "joystick investigator" that prints button/axis values to the dashboard for the same purpose. Always verify the physical control matches the code mapping before you trust it in a match.
Key takeaways
- Bind controls declaratively with CommandXboxController and Trigger objects in RobotContainer.
- Use onTrue/onFalse for one-shot actions, whileTrue/whileFalse for hold-to-run, and prefer two buttons over toggleOnTrue for critical actions.
- Design mappings around the human: split driver/operator, group actions, guard dangerous ones.
- Use the USB Devices tab's live feedback to confirm physical controls match code indices.
Lesson quiz
RequiredAnswer all 3 questions correctly to complete this lesson.
01.When you bind a command to a Trigger with whileTrue(command), what happens?
02.For a critical action, what control scheme is recommended over using toggleOnTrue?
03.How can you confirm that a physical control matches your code's button index?
Answer every question to submit.
All 34 lessons in Drive Team
- Not started:Project 1: A Production-Ready Driver Control Scheme
- Not started:Project 2: A Drivetrain That Survives a Whole Match
- Not started:Project 3: Build a Paper + Spreadsheet Scouting System
- Not started:Project 4: Pull Live OPR & EPA Data with Python
- Not started:Project 5: The One-Page Pre-Match Strategy Brief