Programación basada en comandos, Versión 2020: ¿Qué cambió?
This article provides a summary of changes from the original command-based framework to the 2020 rewrite. This summary is not necessarily comprehensive - for rigorous documentation, as always, refer to the API docs (Java, C++).
Ubicación del paquete
The new command-based framework is located in the wpilibj2
package for Java, and in the frc2
namespace for C++. The new framework must be installed using the instructions: Bibliotecas de comandos de WPILib.
Cambios arquitectónicos mas grandes
La estructura general del framework para la programación basada en comandos ha permanecido predominantemente igual. Aun así hay algunos cambios estructurales de los que los usuarios deberían estar al tanto:
Comandos y Subsistemas como interfaces
Command
(Java, C++) and Subsystem
(Java, C++) are both now interfaces as opposed to abstract classes, allowing advanced users more potential flexibility. CommandBase
and SubsystemBase
abstract base classes are still provided for convenience, but are not required. For more information, see Comandos and Subsistemas.
Clases grupales de múltiples comandos
The CommandGroup
class no longer exists, and has been replaced by a number of narrower classes that can be recursively composed to create more-complicated group structures. For more information see Command Compositions.
Definiciones de comandos in-line
Previously, users were required to write a subclass of Command
in almost all cases where a command was needed. Many of the new commands are designed to allow inline definition of command functionality, and so can be used without the need for an explicit subclass. For more information, see Included Command Types.
Inyección de dependencias de comando
Aun sin un cambio real al código de la librería, el patrón de uso recomendado para el nuevo framework de programación basada en comandos utiliza inyección de dependencias de subsistemas en los comandos, permitiendo que los subsistemas no sean declarados como globales. Este es un patrón mas limpio, de mayor mantenibilidad y mas reusable que el subsistema global promovido previamente. Para mas información véase Estructuración de un proyecto de robot basado en comandos.
Pertenencia de Comando (Solo para C++)
El framework de comandos anterior requería a los usuarios el usar punteros en crudo para todos los comandos, resultando en una perdida de memoria casi inevitable en todos los proyectos basados en comandos de C++, así como la oportunidad para que errores comunes se presentaran, como la doble locación de un comando dentro de un grupos de comandos
El framework ofrece gestión de propiedad para todos los comandos. Los comandos predeterminados y los comandos vinculados a botones generalmente son propiedad del planificador, y los comandos de componentes son propiedad de sus grupos de comandos encapsulantes. Como resultado, los usuarios generalmente nunca deberían asignar un comando en montón con `` nuevo “” a menos que haya una muy buena razón para hacerlo.
La transferencia de propiedad se hace usando perfect forwarding, lo que significa que los rvalues seran moved y los lvalues seran copied (rvalue/lvalue explanation).
Cambios al Planificador
La interrupbilidad de los comandos ahora es responsabilidad del planificador, no de los comandos, y se puede especificar durante la llamada a `` schedule “”.
Los usuarios ahora pueden pasar acciones al planificador que se realizan cada vez que un comando se programa, interrumpe o finaliza normalmente. Esto es muy útil para casos como el registro de eventos.
Cambios al Subsistema
Nota
Para mas información sobre subsistemas, véase Subsistemas.
As noted earlier,
Subsystem
is now an interface (Java, C++); the closest equivalent of the oldSubsystem
is the newSubsystemBase
class. Many of the Sendable-related constructor overloads have been removed to reduce clutter; users can call the setters directly from their own constructor, if needed.initDefaultCommand
ha sido removido; los subsistemas no necesitan más «conocer» sus comandos por default , los que mejor se registran directamente conCommandScheduler
. El nuevo métodosetDefaultCommand
simplemente envuelve la llamadaCommandScheduler
.Los subsistemas ya no «conocen» los comandos que los requieren en ese momento; esto es manejado exclusivamente por el `` CommandScheduler``. Sin embargo, se proporciona un contenedor de conveniencia en el método `` CommandScheduler``.
Cambios a Comandos
Nota
Para mas información sobre comandos, véase Comandos.
As noted earlier,
Command
is now an interface (Java, C++); the closest equivalent of the oldCommand
is the newCommandBase
class. Many of the Sendable-related constructor overloads have been removed to reduce clutter; users can call the setters directly from their own constructor, if needed.Los comandos ya no manejan su propio estado de programación; ahora es responsabilidad del planificador.
El método
interrupted()
ha sido unido al métodoend()
, lo cual ahora agrega un parámetro que especifica si el comando fue interrumpido o no («false» si finalizó normalmente)El método
requires()``ha cambiado su nombre a ``addRequirement()
.void setRunsWhenDisabled(boolean disabled)
has been replaced by an overridable runsWhenDisabled method.void setInterruptible(boolean interruptible)
has been replaced by an overridable getInterruptionBehavior method.Several «decorator» methods have been added to allow easy inline modification of commands (e.g. adding a timeout).
(C++ only) In order to allow the decorators to work with the command ownership model, a CRTP is used via the
CommandHelper
class. Any user-defined Command subclassFoo
must extendCommandHelper<Foo, Base>
whereBase
is the desired base class.
Cambios a PIDSubsystem/PIDCommand
Nota
Para mas información, véase Control PID a través de subsistemas PID y comandos PID, and Control PID en WPILib
Después de los cambios en el PIDController, estas clases ahora se ejecutan sincrónicamente desde el loop principal del robot.
El `` PIDController`` ahora se inyecta a través del constructor, eliminando muchos de los métodos de reenvío. Se puede modificar después de la construcción con `` getController() ``.
PIDCommand
está pensado en gran medida para su uso en línea, como se muestra en el ejemplo GyroDriveCommands (Java, C++).Si los usuarios desean utilizar el PIDCommand mas «tradicionalmente», sobreescribir los metodos protegidos
returnPIDInput()
yusePIDOutput(double output)
ha sido reemplazado modificando los camposm_measurement
ym_useOutput
. De manera similar, en vez de llamar asetSetpoint
, los usuarios pueden modificar el campo protegidom_setpoint
.