Le planificateur de commandes

La classe CommandScheduler (Java, C++) est la classe responsable de l’exécution des commandes. Chaque itération (habituellement une toutes les 20ms), le planificateur sonde tous les boutons enregistrés, planifie les commandes pour l’exécution en conséquence, exécute les corps des commandes de toutes les commandes planifiées, et met fin aux commandes dont l’exécution normale a pris fin ou sont interrompues.

Le CommandScheduler exécute aussi la méthode periodic() de chaque Subsystem enrégistré.

Utiliser le planificateur de commandes

Le CommandScheduler est un singleton, ce qui veux dire qu’il est une classe accessible globalement avec une seule instance. Donc, pour accéder au planificateur, l’utilisateur devra appeler la commande CommandScheduler.getInstance().

En général, l’utilisateur ne doit pas appeler les méthodes du planificateur directement - presque tout les méthodes importantes du planificateur ont des enveloppe de commodité ailleurs (p. ex. dans les interfaces Command et Subsystem).

Cependant, il y a une exception: l’utilisateur doit appeler CommandScheduler.getInstance().run() de la méthode robotPeriodic() de la classe Robot. Si ce n’est pas effectué, le planificateur ne s’exécutera jamais et le cadre d’application des commandes ne fonctionnera pas. Le modèle de projet orienté commande fourni inclus déjà cet appel.

La méthode schedule()

Flow diagram showing how a scheduled command is evaluated to be run.

Pour planifier une commande, les utilisateurs appellent la méthode schedule() (Java, C++. Cette méthode prend une commande (et, en option, une spécification quant à savoir si cette commande est interrompable), et tente de l’ajouter à la liste des commandes actuellement en cours d’exécution, en attendant si elle est déjà en cours d’exécution ou si les ressources qu’elle requiert sont disponibles. Si elle est ajoutée, sa méthode initialize() est appelée.

La séquence d’exécution du planificateur

Note

La méthode initialize() de chaque Command est appelée lorsque la commande est programmée, ce qui n’est pas forcément quand le planificateur s’exécute (sauf si cette commande est liée à un bouton).

Flow diagram that show the sequence of each individual command.

Que fait réellement un seule itération de la méthode run() du planificateur de commandes (Java, C++) ? La section suivante passe en revue la logique d’une itération du planificateur de commandes.

Étape 1: exécuter les méthodes périodique des sous-systèmes

Premièrement, le planificateur exécute la méthode periodic() de chaque Subsystem enregistré.

Étape 2: sonder les déclencheurs de planification de commande

Note

Pour plus d’informations sur le fonctionnement des liens de déclencheurs, voir Liaison de commandes à des déclencheurs

Deuxièmement, le planificateur sonde l’état de tous les déclencheurs enregistres pour voir si des nouvelles commandes qui ont été liées à ces déclencheurs devraient être planifiées. Si les conditions pour planifier une commande liée sont remplies, la commande est planifié et sa méthode initialize() est exécutée.

Étape 3: exécuter/terminer les commandes planifiées

Troisièmement, le planificateur appelle la méthode execute() de chaque commande en cours d’exécution après avoir vérifié si la commande est terminé en appelant la méthode isFinished(). Si la commande est terminé, la méthode end() est appelée aussi, et la commande est dé-planifiée et ses sous-systèmes requis sont libérés.

Notez qui cette séquence d’appels est faite en ordre pour chaque commande - ainsi, une commande peut avoir sa méthode end() appelée avant qu’une autre ait sa méthode execute() appelée. Les commandes sont manipulées dans l’ordre dont elles ont été planifiées.

Étape 4: planifier les commandes par défaut

Finalement, chaque Subsystem enrégistré a sa commande par défaut planifiée (si elle existe). Notez que la méthode initialize() de la commande de défaut sera appelée à ce moment.

Désactiver le Planificateur

Le planificateur peut être désactiver en appelant CommandScheduler.getInstance().disable(). Quand il est désactivé, les commandes schedule() et run() du planificateur ne font rien.

Le planificateur peut être ré-activé en appelant CommandScheduler.getInstance().enable().

Méthodes d’évènement de commande

Parfois, il est désirable que le planificateur exécute une action personnalisée lorsqu’un certain événement de commande (initialisation, exécution ou terminaison) se produit. Cela peut être fait grâce à l’une des trois méthodes suivantes:

onCommandInitialize

La méthode onCommandInitialize (Java, C++) exécute une action spécifiée chaque fois qu’une commande est initialisée.

onCommandExecute

La méthode onCommandExecute (Java, C++) exécute une action spécifiée chaque fois qu’une commande est exécutée.

onCommandFinish

La méthode onCommandFinish (Java, C++) exécute une action spécifiée chaque fois qu’une commande se termine normalement (c’est-à-dire que la méthode isFinished() retourne la valeur logique true).

onCommandInterrupt

La méthode onCommandInterrupt (Java, C++) exécute une action spécifiée chaque fois qu’une commande est interrompue (c’est-à-dire en étant explicitement annulée ou par une autre commande qui partage l’une des ressources qu’elle requiert).

A typical use-case for these methods is adding markers in an event log whenever a command scheduling event takes place, as demonstrated in the SchedulerEventLogging example project (Java, C++):

50
51
52
53
54
55
56
    // Set the scheduler to log Shuffleboard events for command initialize, interrupt, finish
    CommandScheduler.getInstance().onCommandInitialize(command -> Shuffleboard.addEventMarker(
        "Command initialized", command.getName(), EventImportance.kNormal));
    CommandScheduler.getInstance().onCommandInterrupt(command -> Shuffleboard.addEventMarker(
        "Command interrupted", command.getName(), EventImportance.kNormal));
    CommandScheduler.getInstance().onCommandFinish(command -> Shuffleboard.addEventMarker(
        "Command finished", command.getName(), EventImportance.kNormal));