Liaison de commandes à des déclencheurs

Mis à part les commandes autonomes, qui sont planifiées au début de la période autonome, et les commandes par défaut, qui sont automatiquement planifiées chaque fois que leur sous-système n’est pas actuellement en cours d’utilisation, la façon la plus courante d’exécuter une commande est de la lier à un événement déclencheur, comme un bouton appuyé par un opérateur humain. Le paradigme orienté commande rend cela extrêmement facile à faire.

Comme mentionné précédemment, la commande est un paradigme declaratif. En conséquence, la liaison des boutons aux commandes se fait de manière déclarative; l’association d’un bouton et d’une commande est « déclarée » une fois, lors de l’initialisation du robot. La bibliothèque effectue ensuite tout le travail ardu de vérification de l’état du bouton et de planification (ou d’annulation) de la commande selon les besoins, en arrière-plan. Les usagers n’ont qu’à se soucier de la conception de l’interface utilisateur - pas de sa mise en œuvre!

La liaison de commande se fait à travers la classe Trigger (Java, C++) et sa variété de sous-classes Button (Java, C++).

Liaisons déclencheur/bouton

Note

La librairie orientée commande C++ offre deux surcharges pour chaque méthode de liaison de boutons, une qui prend une référence de transfert et une qui prend un pointeur brut. La surcharge de référence de transfert transfère la propriété (en déplaçant ou en copiant selon que la commande est une rvalue ou lvalue) au planificateur, tandis que la surcharge de pointeur brut laisse l’utilisateur responsable de la durée de vie de l’objet de commande. Il est recommandé aux utilisateurs d’utiliser de préférence la surcharge de référence de mise en service à moins qu’il n’y ait un besoin spécifique de conserver une poignée à la commande dans le code d’appel.

Il existe un certain nombre de liaisons disponibles pour la classe Trigger. Toutes ces liaisons planifient automatiquement une commande lorsqu’un événement d’activation de déclencheur se produit - cependant, chaque liaison a un comportement spécifique différent. Button et ses sous-classes ont des liaisons avec des comportements identiques, mais des noms légèrement différents qui correspondent mieux à un bouton plutôt qu’à un événement déclencheur arbitraire.

whenActive/whenPressed

Cette liaison planifie une commande lorsqu’un déclencheur passe de l’état inactif à l’état actif (ou, en conséquence, lorsqu’un bouton déclencheur est initialement appuyé). La commande sera planifiée sur l’itération lorsque l’état change, et ne sera pas planifiée à nouveau à moins que le déclencheur ne devienne inactif, puis actif à nouveau (ou le bouton est libéré, puis appuyé à nouveau).

whileActiveContinuous/whileHeld

Cette liaison planifie une commande à plusieurs reprises pendant qu’un déclencheur est actif (ou, en conséquence, pendant qu’un bouton est maintenu), et l’annule lorsque le déclencheur devient inactif (ou lorsque le bouton est libéré). Notez que la planification d’une commande déjà en cours d’exécution n’a aucun effet ; mais si la commande se termine pendant que le déclencheur est toujours actif, elle sera re-planifiée.

whileActiveOnce/whenHeld

Cette liaison planifie une commande lorsqu’un déclencheur passe de l’état inactif à l’état actif (ou, en conséquence, lorsqu’un bouton est initialement appuyé) et l’annule lorsque le déclencheur redevient inactif (ou que le bouton est libéré). La commande ne sera pas re-planifiée si elle se termine pendant que le déclencheur est toujours actif.

whenInactive/whenReleased

Cette liaison planifie une commande lorsqu’un déclencheur passe de l’état actif à l’état inactif (ou, en conséquence, lorsqu’un bouton est initialement libéré). La commande sera planifiée sur l’itération lorsque l’état change, et ne sera pas re-planifiée à moins que le déclencheur ne devienne actif, puis inactif à nouveau (ou le bouton est appuyé, puis re-relâché).

toggleWhenActive/toggleWhenPressed

Cette liaison bascule une commande, la programmant lorsqu’un déclencheur passe de inactif à actif (ou un bouton est initialement appuyé), et l’annulant sous la même condition si la commande est actuellement en cours d’exécution. Notez que bien que cette fonctionnalité soit prise en charge, les basculements ne sont pas une option fortement recommandée pour le contrôle par l’utilisateur, car ils exigent que le pilote garde une trace de l’état du robot. La méthode préférée est d’utiliser deux boutons; l’un pour allumer et l’autre pour éteindre. L’usage d’une commande StartEndCommand ou d’une commande ConditionalCommand constitue un bon moyen de spécifier les commandes entre lesquelles vous vous basculer.

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

cancelWhenActive/cancelWhenPressed

Cette liaison annule une commande lorsqu’un déclencheur passe d’inactif à actif (ou, par conséquent, lorsqu’un bouton est initialement enfoncé). la commande est alors annulée lorsque l’état change. Elle ne sera pas annulée une seconde fois, sauf si le déclencheur devient inactif puis à nouveau actif (ou si le bouton est relâché et ré-enfoncé). Notez que l’annulation d’une commande qui n’est pas en cours d’exécution n’a aucun effet.

Liaison d’une commande à un bouton joystick

La façon la plus courante de déclencher une commande est de lier une commande à un bouton d’un joystick ou d’un autre HID (dispositif d’interface humaine). Pour ce faire, les utilisateurs doivent utiliser la classe JoystickButton.

Création d’un JoystickButton

Dans le but de créer un JoystickButton, nous avons d’abord besoin d’un objet Joystick. Tous les types de manettes (y compris les manettes de jeu) sont représentés sous forme de code par la classe GenericHID (Java, C++), ou ou une de ses classes filles:

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

Note

When creating a JoystickButton with an XboxController, it is usually a good idea to use the button enum (Java, C++) to get the button number corresponding to a given button.

Une fois le joystick est instantané, les utilisateurs peuvent ensuite le transmettre à un objet JoystickButton (Java, C++):

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

Liaison d’une commande à un JoystickButton

Note

Dans la bibliothèque orientée commande C++, les objets button n’ont pas besoin de survivre après l’appel à une méthode de liaison, de sorte que les méthodes de liaison peuvent être simplement appelées sur une temp.

En mettant tout cela ensemble, il est très simple de lier un bouton à un JoystickButton:

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

Il est utile de noter que les méthodes de liaison de commande renvoient toutes le déclencheur/bouton sur lequel elles ont été initialement appelées, et peuvent donc être enchaînées pour lier plusieurs commandes à différents états du même bouton. Par exemple:

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());

N’oubliez pas que la liaison des boutons est déclarative: les liaisons ne doivent être déclarées qu’une seule fois, idéalement pendant l’initialisation du robot. La bibliothèque gère tout le reste.

Composition de déclencheurs

La classe Trigger (incluant ses sous-classes Button) peut être composée pour créer des déclencheurs composites à travers les méthodes and(), or(), et negate() (ou, en C++, les opérateurs &&, ||, et ! ). Par exemple :

// 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());

Notez que ces méthodes renvoient un Trigger, pas un Button, de sorte que les noms de méthode de liaison Trigger doivent être utilisés même lorsque les boutons sont composés.

Création de votre propre déclencheur personnalisé

Bien que la liaison aux boutons HID soit de loin le cas d’utilisation le plus courant, les utilisateurs avancés peuvent parfois vouloir lier des commandes à des événements déclencheurs arbitraires. Cela peut être facilement fait en écrivant simplement votre propre sous-classe de trigger ou button:

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

Alternativement, cela peut également être fait en ligne en passant un lambda au constructeur de trigger ou 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);