Skip to main content

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​

ButtonFunctionBehavior
R2Primary Action (Hold-to-Run)Triggers the main subsystem action. Activates on press, cancels on release.
L2Secondary Action (Hold-to-Run)Triggers secondary subsystem behavior. Activates on press, cancels on release.
R1Auxiliary Action 1Context-dependent auxiliary control
L1Auxiliary Action 2Context-dependent auxiliary control

Safety Controls​

ButtonFunctionBehavior
Cross (✕)Emergency StopSets all subsystems to OFF/EMPTY states via setDesiredStateCmd. Does NOT directly call stop methods.

Additional Buttons​

ButtonFunction
Circle (○)Available for custom bindings
Square (□)Available for custom bindings
Triangle (△)Available for custom bindings
D-PadAvailable for discrete selections
JoysticksDrive 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​

  1. Consistent Mapping: Use R2/L2 for hold-to-run across all subsystems
  2. State Transitions: Always use setDesiredStateCmd() for state changes
  3. Emergency Safety: Cross button sets safe states, never bypasses the state machine
  4. Compound Triggers: Use .And(), .Or() for complex conditions
  5. Clear Intent: Button names should match their function (e.g., "intakeButton", "shootButton")

Testing in Simulation​

When testing controller bindings:

  1. Connect your PS5 controller
  2. Launch robot simulation
  3. Verify each button in the Driver Station
  4. Check SmartDashboard/Elastic for state changes
  5. Confirm hold-to-run behavior cancels on release
  6. Test emergency stop sets all subsystems to safe states