- FRC Game Manual
- FRC Game Q&A

# Binding Commands to Triggers

Apart from autonomous commands, which are scheduled at the start of the autonomous period, and default commands, which are automatically scheduled whenever their subsystem is not currently in-use, the most common way to run a command is by binding it to a triggering event, such as a button being pressed by a human operator. The command-based paradigm makes this extremely easy to do.

As mentioned earlier, command-based is a declarative programming paradigm. Accordingly, binding buttons to commands is done declaratively; the association of a button and a command is “declared” once, during robot initialization. The library then does all the hard work of checking the button state and scheduling (or canceling) the command as needed, behind-the-scenes. Users only need to worry about designing their desired UI setup - not about implementing it!

Command binding is done through the `Trigger` class (Java, C++).

## Getting a Trigger Instance

To bind commands to conditions, we need a `Trigger` object. There are three ways to get a Trigger object:

### HID Factories

The command-based HID classes contain factory methods returning a `Trigger` for a given button. `CommandGenericHID` has an index-based `button(int)` factory (Java, C++), and its subclasses `CommandXboxController` (Java, C++), `CommandPS4Controller` (Java, C++), and `CommandJoystick` (Java, C++) have named factory methods for each button.

JAVA

    CommandXboxController exampleCommandController = new CommandXboxController(1); // Creates a CommandXboxController on port 1.
    Trigger xButton = exampleCommandController.x(); // Creates a new Trigger object for the `X` button on exampleCommandController

C++

    frc2::CommandXboxController exampleCommandController{1} // Creates a CommandXboxController on port 1
    frc2::Trigger xButton = exampleCommandController.X() // Creates a new Trigger object for the `X` button on exampleCommandController

### JoystickButton

Alternatively, the regular HID classes can be used and passed to create an instance of `JoystickButton` Java, C++), a constructor-only subclass of `Trigger`:

JAVA

    XboxController exampleController = new XboxController(2); // Creates an XboxController on port 2.
    Trigger yButton = new JoystickButton(exampleController, XboxController.Button.kY.value); // Creates a new JoystickButton object for the `Y` button on exampleController

C++

    frc::XboxController exampleController{2} // Creates an XboxController on port 2
    frc2::JoystickButton yButton(&exampleStick, frc::XboxController::Button::kY); // Creates a new JoystickButton object for the `Y` button on exampleController

### Arbitrary Triggers

While binding to HID buttons is by far the most common use case, users may want to bind commands to arbitrary triggering events. This can be done inline by passing a lambda to the constructor of `Trigger`:

JAVA

    DigitalInput limitSwitch = new DigitalInput(3); // Limit switch on DIO 3
    Trigger exampleTrigger = new Trigger(limitSwitch::get);

C++

    frc::DigitalInput limitSwitch{3}; // Limit switch on DIO 3
    frc2::Trigger exampleTrigger([&limitSwitch] { return limitSwitch.Get(); });

## Trigger Bindings

Note

The C++ command-based library offers two overloads of each button binding method - one that takes an rvalue reference (`CommandPtr&&`), and one that takes a raw pointer (`Command*`). The rvalue overload moves ownership to the scheduler, while the raw pointer overload leaves the user responsible for the lifespan of the command object. It is recommended that users preferentially use the rvalue reference overload unless there is a specific need to retain a handle to the command in the calling code.

There are a number of bindings available for the `Trigger` class. All of these bindings will automatically schedule a command when a certain trigger activation event occurs - however, each binding has different specific behavior.

`Trigger` objects do not need to survive past the call to a binding method, so the binding methods may be simply called on a temp. Remember that button binding is declarative: bindings only need to be declared once, ideally some time during robot initialization. The library handles everything else.

Note

The `Button` subclass is deprecated, and usage of its binding methods should be replaced according to the respective deprecation messages in the API docs.

### onTrue

This binding schedules a command when a trigger changes from `false` to `true` (or, accordingly, when a button changes is initially pressed). The command will be scheduled on the iteration when the state changes, and will not be scheduled again unless the trigger becomes `false` and then `true` again (or the button is released and then re-pressed).

JAVA

    65    // Retract the intake with the Y button
    66    m_driverController.y().onTrue(m_intake.retractCommand());

C++

    28  // Deploy the intake with the X button
    29  m_driverController.X().OnTrue(m_intake.IntakeCommand());

The `onFalse` binding is identical, only that it schedules on `false` instead of on `true`.

### whileTrue

This binding schedules a command when a trigger changes from `false` to `true` (or, accordingly, when a button is initially pressed) and cancels it when the trigger becomes `false` again (or the button is released). The command will not be re-scheduled if it finishes while the trigger is still `true`. For the command to restart if it finishes while the trigger is `true`, wrap the command in a `RepeatCommand`, or use a `RunCommand` instead of an `InstantCommand`.

JAVA

    49    // Schedule `exampleMethodCommand` when the Xbox controller's B button is pressed,
    50    // cancelling on release.
    51    m_driverController.b().whileTrue(m_exampleSubsystem.exampleMethodCommand());

C++

    27  // Schedule `ExampleMethodCommand` when the Xbox controller's B button is
    28  // pressed, cancelling on release.
    29  m_driverController.B().WhileTrue(m_subsystem.ExampleMethodCommand());

The `whileFalse` binding is identical, only that it schedules on `false` and cancels on `true`.

### toggleOnTrue

This binding toggles a command, scheduling it when a trigger changes from `false` to `true` (or a button is initially pressed), and canceling it under the same condition if the command is currently running. Note that while this functionality is supported, toggles are not a highly-recommended option for user control, as they require the driver to keep track of the robot state. The preferred method is to use two buttons; one to turn on and another to turn off. Using a StartEndCommand or a ConditionalCommand is a good way to specify the commands that you want to be want to be toggled between.

JAVA

    78    // Toggle compressor with the Start button
    79    m_driverController.start().toggleOnTrue(m_pneumatics.disableCompressorCommand());

C++

    41  // Toggle compressor with the Start button
    42  m_driverController.Start().ToggleOnTrue(
    43      m_pneumatics.DisableCompressorCommand());

The `toggleOnFalse` binding is identical, only that it toggles on `false` instead of on `true`.

## Chaining Calls

It is useful to note that the command binding methods all return the trigger that they were called on, and thus can be chained to bind multiple commands to different states of the same trigger. For example:

JAVA

    exampleButton
        // Binds a FooCommand to be scheduled when the button is pressed
        .onTrue(new FooCommand())
        // Binds a BarCommand to be scheduled when that same button is released
        .onFalse(new BarCommand());

C++

    exampleButton
        // Binds a FooCommand to be scheduled when the button is pressed
        .OnTrue(FooCommand().ToPtr())
        // Binds a BarCommand to be scheduled when that same button is released
        .OnFalse(BarCommand().ToPtr());

## Composing Triggers

The `Trigger` class can be composed to create composite triggers through the `and()`, `or()`, and `negate()` methods (or, in C++, the `&&`, `||`, and `!` operators). For example:

JAVA

    // Binds an ExampleCommand to be scheduled when both the 'X' and 'Y' buttons of the driver gamepad are pressed
    exampleCommandController.x()
        .and(exampleCommandController.y())
        .onTrue(new ExampleCommand());

C++

    // Binds an ExampleCommand to be scheduled when both the 'X' and 'Y' buttons of the driver gamepad are pressed
    (exampleCommandController.X()
        && exampleCommandController.Y())
        .OnTrue(ExampleCommand().ToPtr());

## Debouncing Triggers

To avoid rapid repeated activation, triggers (especially those originating from digital inputs) can be debounced with the WPILib Debouncer class using the debounce method:

JAVA

    // debounces exampleButton with a 0.1s debounce time, rising edges only
    exampleButton.debounce(0.1).onTrue(new ExampleCommand());
    // debounces exampleButton with a 0.1s debounce time, both rising and falling edges
    exampleButton.debounce(0.1, Debouncer.DebounceType.kBoth).onTrue(new ExampleCommand());

C++

    // debounces exampleButton with a 100ms debounce time, rising edges only
    exampleButton.Debounce(100_ms).OnTrue(ExampleCommand().ToPtr());
    // debounces exampleButton with a 100ms debounce time, both rising and falling edges
    exampleButton.Debounce(100_ms, Debouncer::DebounceType::Both).OnTrue(ExampleCommand().ToPtr());