Controller Map
This page documents the PS5 controller conventions used in TEAM1771 robotics code.
PS5 Controller Button Layout
We use a PS5 controller with the following standardized button mappings:
Primary Controls
| Button | Function | Behavior |
|---|---|---|
| R2 | Primary Action (Hold-to-Run) | Triggers the main subsystem action. Activates on press, cancels on release. |
| L2 | Secondary Action (Hold-to-Run) | Triggers secondary subsystem behavior. Activates on press, cancels on release. |
| R1 | Auxiliary Action 1 | Context-dependent auxiliary control |
| L1 | Auxiliary Action 2 | Context-dependent auxiliary control |
Safety Controls
| Button | Function | Behavior |
|---|---|---|
| Cross (✕) | Emergency Stop | Sets all subsystems to OFF/EMPTY states via setDesiredStateCmd. Does NOT directly call stop methods. |
Additional Buttons
| Button | Function |
|---|---|
| Circle (○) | Available for custom bindings |
| Square (□) | Available for custom bindings |
| Triangle (△) | Available for custom bindings |
| D-Pad | Available for discrete selections |
| Joysticks | Drive control and continuous inputs |
Key Principles
Hold-to-Run Pattern
Both R2 and L2 use the hold-to-run pattern:
- Press: Activates the desired state
- Hold: State remains active
- Release: Cancels and returns to default/idle state
This pattern ensures:
- ✅ Predictable behavior
- ✅ Immediate cancellation on release
- ✅ Safety through deliberate action
Emergency Stop (Cross Button)
The emergency stop button:
- Sets subsystems to safe states (OFF, EMPTY, IDLE, etc.)
- Uses
setDesiredStateCmd(STATE::OFF)or similar - Does NOT call
.stop()or other direct control methods - Allows the subsystem's state machine to handle the transition safely
State-Based Control
All button bindings should:
- Use
setDesiredStateCmd()to request state changes - Let the subsystem's state machine handle transitions
- Avoid directly controlling motors or mechanisms
- Work through the command-based framework
Example Usage
// In RobotContainer.cpp
// R2 - Primary action (hold-to-run)
m_driverController.R2().OnTrue(m_exampleSubsystem.setDesiredStateCmd(ExampleSubsystem::STATE::ON))
.OnFalse(m_exampleSubsystem.setDesiredStateCmd(ExampleSubsystem::STATE::OFF));
// L2 - Secondary action (hold-to-run)
m_driverController.L2().OnTrue(m_exampleSubsystem.setDesiredStateCmd(ExampleSubsystem::STATE::SECONDARY))
.OnFalse(m_exampleSubsystem.setDesiredStateCmd(ExampleSubsystem::STATE::OFF));
// Cross - Emergency stop (sets all subsystems to safe states)
m_driverController.Cross().OnTrue(
m_exampleSubsystem.setDesiredStateCmd(ExampleSubsystem::STATE::OFF)
.AndThen(m_anotherSubsystem.setDesiredStateCmd(AnotherSubsystem::STATE::EMPTY))
);
Best Practices
- Consistent Mapping: Use R2/L2 for hold-to-run across all subsystems
- State Transitions: Always use
setDesiredStateCmd()for state changes - Emergency Safety: Cross button sets safe states, never bypasses the state machine
- Compound Triggers: Use
.And(),.Or()for complex conditions - Clear Intent: Button names should match their function (e.g., "intakeButton", "shootButton")
Testing in Simulation
When testing controller bindings:
- Connect your PS5 controller
- Launch robot simulation
- Verify each button in the Driver Station
- Check SmartDashboard/Elastic for state changes
- Confirm hold-to-run behavior cancels on release
- Test emergency stop sets all subsystems to safe states