¿Qué es la programación «basada en comandos»?

WPILib admite una metodología de programación de robots llamada programación «basada en comandos». En general, «basado en comandos» puede referirse tanto al paradigma de programación general como al conjunto de recursos de la biblioteca WPILib incluidos para facilitarlo.

La programación «basada en comandos» es un ejemplo de lo que se conoce como design pattern. Es una forma general de organizar el código de un robot que se adapta bien a un problema-espacio en particular. No es la única forma de escribir un programa de robot, pero es muy eficaz; el código de robot basado en comandos tiende a ser limpio, extensible y (con algunos trucos) fácil de reutilizar año tras año.

El paradigma basado en comandos también es un ejemplo de lo que se conoce como programación declarative. En la programación declarativa, el énfasis se pone en qué debería hacer el programa, en lugar de cómo debería hacerlo. Por lo tanto, las bibliotecas basadas en comandos permiten a los usuarios definir los comportamientos deseados del robot al tiempo que minimizan la cantidad de lógica de robot iteración por iteración que deben escribir. Por ejemplo, en un programa basado en comandos, un usuario puede especificar que «el robot debe realizar una acción cuando se presiona un botón» (tenga en cuenta el uso de lambda):

aButton.whenPressed(intake::run);

Por el contrario, en un programa ordinario imperative, el usuario tendría que comprobar el estado del botón en cada iteración y realizar la acción adecuada en función del estado del botón.

if(aButton.get()) {
  if(!pressed) {
    intake.run();
    pressed = true;
  }
} else {
  pressed = false;
}

Subsistemas y comandos

image of subsystems and commands

El patrón basado en comandos se basa en dos abstracciones centrales: comandos y subsistemas.

Los subsistemas son la unidad básica de la organización del robot en el paradigma basado en el diseño. Los subsistemas encapsulan hardware de robot de nivel inferior (como controladores de motor, sensores y/o actuadores neumáticos), y definen las interfaces a través de las cuales el resto del código del robot puede acceder a ese hardware. Los subsistemas permiten a los usuarios «ocultar» la complejidad interna de su hardware real del resto de su código - esto simplifica el resto del código del robot, y permite cambios en los detalles internos de un subsistema sin cambiar también el resto del código del robot. Los subsistemas implementan la interfaz Subsystem.

Los comandos definen acciones o comportamientos de robots de alto nivel que utilizan los métodos definidos por los subsistemas. Un comando es una simple máquina de estado que se está inicializando, ejecutándose, finalizando o inactiva. Los usuarios escriben un código que especifica qué acción se debe tomar en cada estado. Los comandos simples se pueden componer en «grupos de comandos» para realizar tareas más complicadas. Los comandos, incluidos los grupos de comandos, implementan la interfaz de Comando.

Cómo se ejecutan los comandos

Nota

Para obtener una explicación más detallada, consulte: doc: command-scheduler.

Los comandos son ejecutados por el CommandScheduler (Java, C++), una clase singleton que está en el núcleo de la biblioteca basada en comandos. El CommandScheduler se encarga de sondear los botones en busca de nuevos comandos para programar, comprobando los recursos requeridos por esos comandos para evitar conflictos, ejecutando los comandos actualmente programados, y eliminando los comandos que han terminado o han sido interrumpidos. El método run() del programador puede ser llamado desde cualquier lugar del código del usuario; generalmente se recomienda llamarlo desde el método robotPeriodic() de la clase Robot, que se ejecuta con una frecuencia por defecto de 50Hz (una vez cada 20ms).

Se pueden ejecutar varios comandos al mismo tiempo, siempre que no requieran los mismos recursos en el robot. La administración de recursos se maneja por subsistema: los comandos pueden especificar con qué subsistemas interactúan, y el programador nunca programará más de un comando que requiera un subsistema determinado a la vez. Esto asegura que, por ejemplo, los usuarios no terminarán con dos piezas de código diferentes que intenten configurar el mismo controlador de motor a diferentes valores de salida. Si se programa un nuevo comando que requiere un subsistema que ya está en uso, interrumpirá el comando actualmente en ejecución que requiere ese subsistema (si el comando se programó como interrumpible), o de lo contrario no se programará.

Los subsistemas también se pueden asociar con «comandos predeterminados» que se programarán automáticamente cuando ningún otro comando esté utilizando el subsistema. Esto es útil para acciones continuas «en segundo plano», como controlar el accionamiento del robot o mantener un brazo sujeto en un punto de ajuste.

Cuando se programa un comando, su método initialize() se llama una vez. Su método execute() se llama una vez por llamada a CommandScheduler.getInstance().run(). Un comando no está programado y tiene su método end(boolean interrumpted) llamado cuando su método isFinished() devuelve verdadero, o es interrumpido (ya sea por otro comando con el que comparte un subsistema, o por ser cancelado).

Grupos de comandos

A menudo es deseable construir comandos complejos a partir de piezas simples. Esto se puede lograr componiendo comandos en «grupos de comandos.» Un command group es un comando que contiene varios comandos dentro de él, que se ejecutan en paralelo o en secuencia. La biblioteca basada en comandos proporciona varios tipos de grupos de comandos para que los usen los equipos, y se anima a los usuarios a que escriban los suyos propios, si lo desean. Como los propios grupos de comandos implementan la interfaz de Comando, son componibles recursivamente se pueden incluir grupos de comandos dentro de otros grupos de comandos. Esto proporciona una forma extremadamente poderosa de crear acciones de robot complejas con una biblioteca simple.

Crear un proyecto de robot

La creación de un proyecto se detalla en Creando un programa para el robot. Seleccione «Template», luego su lenguaje de programación y luego «New Command Robot» para crear un programa básico de robot a base de comandos.

Cuando usted creé un proyecto New Command Robot, la nueva biblioteca de proveedores basada en comandos se importa automáticamente. Si importó un proyecto de 2019 o creó un tipo de proyecto diferente, se importa la biblioteca de comandos anterior y es necesario importar la nueva biblioteca de proveedores basada en comandos por Bibliotecas de 3ros y elimine la antigua biblioteca de comandos.