Binding Commands to Triggers

Binding Commands to Triggers

Gán command với nút bấm, điều kiện hoặc trigger từ tay cầm.

Gán command với nút bấm, điều kiện hoặc trigger từ tay cầm.

Level

Advanced

Source

Source

Author

Author

FTC Lib

FTC Lib

Translator

Translator

FTC26749 aDudu

FTC26749 aDudu

Date Published

Date Published

Jan 18, 2026

Jan 18, 2026

package com.arcrobotics.ftclib.command.button
package com.arcrobotics.ftclib.command.button

Ngoài các command tự động (autonomous commands) — được lập lịch khi bắt đầu giai đoạn autonomous — và default commands — được tự động lập lịch bất cứ khi nào subsystem của chúng không đang được sử dụng — thì cách phổ biến nhất để chạy một commandgắn (bind) nó với một sự kiện kích hoạt (triggering event), chẳng hạn như khi người điều khiển nhấn một nút.

Mô hình command-based giúp việc này trở nên cực kỳ đơn giản.

Như đã đề cập trước đó, command-based là một mô hình khai báo (declarative paradigm). Do đó, việc gắn nút với command cũng được thực hiện theo cách khai báo; mối liên hệ giữa một nút và một command được “khai báo” một lần, trong quá trình khởi tạo robot.

Thư viện sau đó sẽ tự động:

  • Kiểm tra trạng thái của nút

  • Lập lịch (schedule) hoặc hủy (cancel) command khi cần

Tất cả đều được xử lý ở phía sau (behind-the-scenes).
Người dùng chỉ cần quan tâm đến việc thiết kế giao diện điều khiển mong muốn, chứ không phải cách hiện thực nó.

Việc gắn command được thực hiện thông qua lớp Trigger và các lớp con Button của nó.

Trigger / Button Bindings

Lớp Trigger cung cấp nhiều kiểu binding khác nhau.
Tất cả các binding này đều:

  • Tự động lập lịch một command

  • Khi xảy ra một sự kiện kích hoạt nhất định

Tuy nhiên, mỗi binding có hành vi cụ thể khác nhau.

Lớp Button và các lớp con của nó có các binding tương tự về hành vi, nhưng có tên gọi khác một chút để phù hợp hơn với khái niệm “nút bấm” thay vì một trigger tổng quát.

whenActive / whenPressed

Binding này lập lịch một command khi:

  • Trigger chuyển từ không hoạt động → hoạt động

  • (Tương ứng: khi một nút được nhấn lần đầu)

Command sẽ được lập lịch ở iteration mà trạng thái thay đổi, và:

  • Sẽ không được lập lịch lại

  • Trừ khi trigger trở về không hoạt động rồi lại hoạt động
    (hoặc nút được nhả ra rồi nhấn lại)

whileActiveContinuous / whileHeld

Binding này:

  • Lập lịch command liên tục trong khi trigger đang hoạt động
    (hoặc trong khi nút đang được giữ)

  • Hủy command khi trigger trở nên không hoạt động
    (hoặc khi nút được nhả)

Lưu ý:

  • Việc lập lịch một command đang chạy sẽ không có tác dụng

  • Nhưng nếu command kết thúc trong khi trigger vẫn đang hoạt động, nó sẽ được lập lịch lại

whileActiveOnce / whenHeld

Binding này:

  • Lập lịch command khi trigger chuyển từ không hoạt động → hoạt động
    (hoặc khi nút được nhấn lần đầu)

  • Hủy command khi trigger trở lại không hoạt động
    (hoặc khi nút được nhả)

Command:

  • Sẽ không được lập lịch lại

  • Nếu nó kết thúc trong khi trigger vẫn đang hoạt động

whenInactive / whenReleased

Binding này lập lịch command khi:

  • Trigger chuyển từ hoạt động → không hoạt động

  • (Tương ứng: khi nút được nhả lần đầu)

Command:

  • Được lập lịch tại iteration mà trạng thái thay đổi

  • Không được lập lịch lại

  • Trừ khi trigger lại trở nên hoạt động rồi không hoạt động
    (hoặc nút được nhấn rồi nhả lại)

toggleWhenActive / toggleWhenPressed

Binding này bật/tắt (toggle) một command:

  • Lập lịch command khi trigger chuyển từ không hoạt động → hoạt động
    (hoặc khi nút được nhấn)

  • Hủy command dưới cùng điều kiện nếu command đang chạy

Lưu ý:

  • Mặc dù được hỗ trợ, toggle không được khuyến khích cao cho điều khiển người dùng

  • Vì người lái phải tự ghi nhớ trạng thái của robot

Từ phiên bản v1.2.0 (đóng góp bởi Ethan Leitner):

  • Binding toggle có thêm tùy chọn chuyển đổi giữa hai command

  • Đây là sự thay thế cho ConditionalCommand khi dùng toggle

  • Chỉ cần truyền hai command vào phương thức thay vì một, binding sẽ toggle giữa hai command đó

cancelWhenActive / cancelWhenPressed

Binding này:

  • Hủy một command khi trigger chuyển từ không hoạt động → hoạt động
    (hoặc khi nút được nhấn)

Command:

  • Bị hủy ở iteration mà trạng thái thay đổi

  • Không bị hủy lại

  • Trừ khi trigger trở về không hoạt động rồi lại hoạt động
    (hoặc nút được nhả rồi nhấn lại)

Lưu ý:

  • Hủy một command không đang chạy sẽ không có tác dụng

Binding a Command to a Gamepad Button

(Gắn Command với nút Gamepad)

Cách phổ biến nhất để kích hoạt một command là:

  • Gắn command với một nút trên gamepad

Creating a GamepadButton

(Tạo GamepadButton)

Để tạo một GamepadButton, trước hết ta cần một GamepadEx.

GamepadEx driverOp = new GamepadEx(gamepad1);
GamepadEx toolOp = new GamepadEx(gamepad2);
GamepadEx driverOp = new GamepadEx(gamepad1);
GamepadEx toolOp = new GamepadEx(gamepad2);

Sau khi object được khởi tạo, người dùng có thể truyền nó vào lớp GamepadButton.

Button exampleButton = new GamepadButton(
    driverOp, GamepadKeys.Button.A
);
// hoặc có thể dùng GamepadButton đã được map sẵn
// trong lớp GamepadEx
driverOp.getGamepadButton(GamepadKeys.Button.A);
Button exampleButton = new GamepadButton(
    driverOp, GamepadKeys.Button.A
);
// hoặc có thể dùng GamepadButton đã được map sẵn
// trong lớp GamepadEx
driverOp.getGamepadButton(GamepadKeys.Button.A);

Binding a Command to a Button

(Gắn Command với Button)

Kết hợp tất cả lại với nhau, việc gắn một command vào Button là rất đơn giản.

exampleButton.whenPressed(new ExampleCommand());
/* Việc dùng InstantCommand cũng rất hữu ích */
exampleButton.whenPressed(new InstantCommand(() -> {
    // phần hiện thực Runnable.run() của bạn ở đây
}));
exampleButton.whenPressed(new ExampleCommand());
/* Việc dùng InstantCommand cũng rất hữu ích */
exampleButton.whenPressed(new InstantCommand(() -> {
    // phần hiện thực Runnable.run() của bạn ở đây
}));

Lưu ý quan trọng:

  • Các phương thức binding đều trả về trigger/button mà chúng được gọi ban đầu

  • Do đó, chúng có thể được chain (nối chuỗi) để gắn nhiều command vào các trạng thái khác nhau của cùng một nút

Ví dụ:

exampleButton
    // Gắn FooCommand khi nút A được nhấn
    .whenPressed(new FooCommand())
    // Gắn BarCommand khi nút đó được nhả
    .whenReleased(new BarCommand());
exampleButton
    // Gắn FooCommand khi nút A được nhấn
    .whenPressed(new FooCommand())
    // Gắn BarCommand khi nút đó được nhả
    .whenReleased(new BarCommand());

Hoặc khi khởi tạo button:

Button exampleButton = new GamepadButton(
    driverOp, GamepadKeys.Button.A
    // sau đó gắn command
).whenPressed(new FooCommand())
 .whenReleased(new BarCommand());
Hoặc dùng mapping trong GamepadEx:
driverOp.getGamepadButton(GamepadKeys.Button.A)
    .whenPressed(new FooCommand())
    .whenReleased(new BarCommand());
Button exampleButton = new GamepadButton(
    driverOp, GamepadKeys.Button.A
    // sau đó gắn command
).whenPressed(new FooCommand())
 .whenReleased(new BarCommand());
Hoặc dùng mapping trong GamepadEx:
driverOp.getGamepadButton(GamepadKeys.Button.A)
    .whenPressed(new FooCommand())
    .whenReleased(new BarCommand());

Hãy nhớ:

  • Việc gắn button là khai báo

  • Chỉ cần khai báo một lần, tốt nhất là trong quá trình khởi tạo robot

  • Thư viện sẽ xử lý mọi thứ còn lại

Composing Triggers

(Tổ hợp Trigger)

Lớp Trigger (bao gồm cả các lớp con Button) có thể được tổ hợp để tạo trigger phức hợp bằng các phương thức:

  • and()

  • or()

  • negate()

Ví dụ:

// Gắn ExampleCommand khi cả hai nút 'X' và 'Y'
// trên gamepad của driver đều được nhấn
new GamepadButton(driverOp, GamepadKeys.Button.X)
    .and(new GamepadButton(exampleController, GamepadKeys.Button.Y))
    .whenActive(new ExampleCommand());
// Gắn ExampleCommand khi cả hai nút 'X' và 'Y'
// trên gamepad của driver đều được nhấn
new GamepadButton(driverOp, GamepadKeys.Button.X)
    .and(new GamepadButton(exampleController, GamepadKeys.Button.Y))
    .whenActive(new ExampleCommand());

Lưu ý:

  • Các phương thức này trả về Trigger, không phải Button

  • Vì vậy, phải dùng tên phương thức binding của Trigger

  • Kể cả khi các thành phần là Button

Creating Your Own Custom Trigger

(Tạo Trigger tùy chỉnh)

Mặc dù gắn với button là trường hợp phổ biến nhất, nhưng người dùng nâng cao đôi khi muốn:

  • Gắn command với sự kiện kích hoạt tùy ý

Điều này có thể thực hiện bằng cách:

  • Tạo lớp con của Trigger hoặc Button

    public class ExampleTrigger extends Trigger {
      @Override
      public boolean get() {
        // Trả về true nếu trigger đang hoạt động
      }
    }
    public class ExampleTrigger extends Trigger {
      @Override
      public boolean get() {
        // Trả về true nếu trigger đang hoạt động
      }
    }

Hoặc có thể làm inline bằng cách truyền một lambda vào constructor của Trigger hoặc Button:

// Giả sử "condition" là một object có
// phương thức get() trả về trạng thái trigger
Trigger exampleTrigger = new Trigger(condition::get);
// Giả sử "condition" là một object có
// phương thức get() trả về trạng thái trigger
Trigger exampleTrigger = new Trigger(condition::get);

Cách này có thể dùng để hiện thực một “điều kiện kích hoạt”,
ví dụ như tín hiệu từ sensor.

Khi trigger được kích hoạt:

  • Bạn có thể lập lịch hoặc hủy các command tương ứng.

ADUDU

A proud team of passionate Robotics Enthusiasts competing in nation-wide Technology competitions in Vietnam, the FIRST Tech Challenge and the FIRST Robotics Competition.

Copyright ©

, all rights reserved

Made by aDudu's Programming Department

made by aDudu

made by aDudu

Binding Commands to Triggers