Enlazando comandos a Triggers

Además de los comandos autónomos, que se programan al inicio del período autónomo, y los comandos predeterminados, que se programan automáticamente cuando su subsistema no está en uso, la forma más común de ejecutar un comando es vinculándolo a un evento de activación, como un botón que presiona un operador humano. El paradigma basado en comandos hace que esto sea extremadamente fácil de hacer.

Como se ha mencionado anteriormente, el paradigma basado en comandos es declarativo. En consecuencia, la vinculación de los botones a los comandos se realiza de forma declarativa; la asociación de un botón y un comando se «declara» una vez, durante la inicialización del robot. La biblioteca hace entonces todo el trabajo duro de comprobar el estado del botón y programar (o cancelar) el comando según sea necesario, entre bastidores. Los usuarios sólo tienen que preocuparse de diseñar la configuración de la interfaz de usuario deseada, no de implementarla.

La vinculación de comandos se realiza a través de la clase Trigger (Java, C++) y sus diversas subclases Button (Java, C++).

Enlaces de gatillo / botón

Nota

La biblioteca basada en comandos de C++ ofrece dos sobrecargas de cada método de enlace de botón: una que toma una referencia de reenvío y otra que toma un puntero sin formato. La sobrecarga de referencia de reenvío transfiere la propiedad (ya sea moviendo o copiando dependiendo de si el comando es un rvalue o un lvalue <http://thbecker.net/articles/rvalue_references/section_01.html> __) al programador, mientras que la sobrecarga del puntero sin formato deja al usuario responsable de la vida útil del objeto de comando. Se recomienda que los usuarios usen preferentemente la sobrecarga de referencia de reenvío a menos que exista una necesidad específica de retener un identificador para el comando en el código de llamada.

Hay varios enlaces disponibles para la clase Trigger. Todos estos enlaces programarán automáticamente un comando cuando se produzca un determinado evento de activación de botón; sin embargo, cada enlace tiene un comportamiento específico diferente. Button y sus subclases tienen enlaces con comportamientos idénticos, pero nombres ligeramente diferentes que combinan mejor con un botón en lugar de un evento de activación arbitrario.

whenActive/whenPressed

Esta vinculación programa un comando cuando un botón cambia de inactivo a activo (o, en consecuencia, cuando se presiona inicialmente un cambio de botón). El comando se programará en la iteración cuando cambie el estado, y no se programará nuevamente a menos que el botón se vuelva inactivo y luego se active nuevamente (o se suelte el botón y luego se vuelva a presionar).

whileActiveContinuous/whileHeld

Esta vinculación programa un comando repetidamente mientras un botón está activo (o, en consecuencia, mientras se mantiene presionado un botón) y lo cancela cuando el disparador se vuelve inactivo (o cuando se suelta el botón). Tenga en cuenta que programar un comando que ya se esté ejecutando no tiene ningún efecto; pero si el comando finaliza mientras el botón o gatillo aún está activo, se reprogramará.

whileActiveOnce/whenHeld

Esta vinculación programa un comando cuando un botón o gatillo cambia de inactivo a activo (o, en consecuencia, cuando se presiona un botón inicialmente) y lo cancela cuando el botón vuelve a estar inactivo (o se suelta el botón). El comando no se reprogramará si finaliza mientras el botón aún está activo.

whenInactive/whenReleased

Este enlace programa un comando cuando un botón o gatillo cambia de activo a inactivo (o, en consecuencia, cuando se suelta inicialmente un botón). El comando se programará en la iteración cuando cambie el estado y no se reprogramará a menos que el botón o gatillo se active y luego se vuelva inactivo (o se presione el botón y luego se vuelva a soltar).

toggleWhenActive/toggleWhenPressed

Esta vinculación alterna un comando, programándolo cuando un disparador cambia de inactivo a activo (o se pulsa inicialmente un botón), y cancelándolo bajo la misma condición si el comando se está ejecutando actualmente. Tenga en cuenta que, aunque esta funcionalidad es compatible, los toggles no son una opción muy recomendable para el control del usuario, ya que requieren que el controlador realice un seguimiento del estado del robot. El método preferido es utilizar dos botones; uno para encender y otro para apagar. El uso de un Comando de inicio y fin o un Comando condicional es una buena manera de especificar los comandos que se quieren alternar.

myButton.toggleWhenPressed(new StartEndCommand(mySubsystem::onMethod,
    mySubsystem::offMethod,
    mySubsystem));

cancelWhenActive/cancelWhenPressed

Esta vinculación cancela un comando cuando un botón o gatillo cambia de inactivo a activo(o, en consecuencia, cuando un botón es presionado inicialmente). el comando es cancelado en la iteración cuando el estado cambia, y no será cancelado a menos que el botón o gatillo cambie de inactivo a activo de nuevo (o se suelte el botón y se vuelva a presionar). Note que cancelar un comando que no funciona al momento no tiene efecto.

Vincular un comando a un botón del joystick

La manera más común para desencadenar un comando es vincular un comando a un botón en un joystick o algún otro DIH (dispositivo para intervención humana). Para hace resto , los usuarios deben de utilizar la clase JoystickButton.

Crear un JoystickButton

Para crear un JoystickButton, primero necesitamos un Joystick. Todos los tipos de joysticks (incluyendo los gamepads) están representados en el código por la clase GenericHID (Java, C++), o una de sus subclases:

Joystick exampleStick = new Joystick(1); // Creates a joystick on port 1
XboxController exampleController = new XboxController(2); // Creates an XboxController on port 2.

Nota

Cuando se crea un JoystickButton con un control de Xbox, suele ser una buena idea utilizar el botón enum (Java, C++) para obtener el número de botón correspondiente a un determinado botón.

Después de la instanciación del joystick, los usuarios pueden pasarlo a un objeto JoystickButton (Java, C++):

JoystickButton exampleButton = new JoystickButton(exampleStick, 1); // Creates a new JoystickButton object for button 1 on exampleStick

Vincular un comando a un JoystickButton

Nota

En la biblioteca a base de comandos de C++ no necesita llegar después de la llamada a un método de vinculación, entonces los métodos de vinculación podrán ser llamados solamente de manera temporal.

Poniéndolo todo junto, es muy sencillo vincular un botón a un JoystickButton:

// Binds an ExampleCommand to be scheduled when the trigger of the example joystick is pressed
exampleButton.whenPressed(new ExampleCommand());

Es útil notar que los métodos de vinculación de comandos todos devuelven el gatillo/botón al cual fueron inicialmente vinculados a , entonces puede ser encadenado a vincular múltiples comandos a diferentes estados del mismo botón. Por ejemplo:

exampleButton
    // Binds a FooCommand to be scheduled when the `X` button of the driver gamepad is pressed
    .whenPressed(new FooCommand())
    // Binds a BarCommand to be scheduled when that same button is released
    .whenReleased(new BarCommand());

Recuerde que la vinculación de botones es declarativa: los vínculos solo se necesitan declarar una vez, idealmente durante la inicialización del robot. La biblioteca maneja el resto.

Componer botones

La clase Trigger``(incluye sus subclases ``Button) puede estar compuesta para crear botones compuestos a través de los métodos and(), or(), y negate() (o, en C++, los operadores &&, ||, y ! ). Por ejemplo:

// Binds an ExampleCommand to be scheduled when both the 'X' and 'Y' buttons of the driver gamepad are pressed
new JoystickButton(exampleController, XBoxController.Button.kX.value)
    .and(new JoystickButton(exampleController, XboxController.Button.kY.value))
    .whenActive(new ExampleCommand());

Note que estos métodos devuelven un Trigger, no un Button, entonces los nombres de métodos de vinculación Trigger deben ser usados cuando los botones se componen.

Crear tu botón personalizado

Si bien la vinculación a botones HID es, con mucho, el caso de uso más común, es posible que los usuarios avanzados ocasionalmente deseen vincular comandos a eventos de activación arbitrarios. Esto se puede hacer fácilmente simplemente escribiendo su propia subclase de trigger o button:

public class ExampleTrigger extends Trigger {
  @Override
  public boolean get() {
    // This returns whether the trigger is active
  }
}

Alternativamente, esto también se puede realizar en línea pasando un lambda al constructor de un trigger o un button:

// Here it is assumed that "condition" is an object with a method "get" that returns whether the trigger should be active
Trigger exampleTrigger = new Trigger(condition::get);