2020基于命令的重写:什么改变了?

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++).

包装位置

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: WPILib命令库.

主要构筑变化

基于命令的框架的总体结构基本保持不变。然而,仍有一些用户需要注意的主要体系结构变化:

命令和子系统作为接口

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 指令 and 子系统.

多命令组类

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.

内联命令定义

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.

注入命令依赖项

虽然不是对库的编码的实际改变,但是新的基于命令的框架的推荐使用模式利用子系统依赖性注入命令,因此子系统不被声明为全局。这是一种更清洁、更可维护、更可重用的模式,而不是以前所提倡的全局子系统模式。有关更多信息,请参见 构建基于命令的机器人项目.

命令所有权(C++)

以前的命令框架要求用户对所有命令使用原始指针,从而导致在所有基于C ++命令的项目中几乎不可避免的内存泄漏,并且为常见错误留出了空间,例如在命令组内双重分配命令。

新的命令框架为所有命令提供所有权管理。绑定到按钮的默认命令和命令通常由调度器拥有,组件命令由它们的封装命令组拥有。因此,用户通常不应该堆分配new命令。除非有一个很好的理由这样做。

所有权的转移是通过完美的转发完成的,<https://cpppatterns.com/patterns/perfect-forwarding.html>`__,这意味着右值将被移动,左值将被复制(右值/左值说明<http://thbecker.net/articles/rvalue_references/section_01.html>`__).

对调度程序的更改

  • Scheduler has been renamed to CommandScheduler (Java, C++).

  • 现在命令的可中断性是调度程序的责任,而不是命令的责任,可以在调用``schedule’’时指定。

  • 用户现在可以将操作传递给调度程序,只要命令被调度,中断或正常结束,便会采取这些操作。这对于事件记录之类的情况非常有用。

子系统变化

备注

有关子系统的更多信息,请参见子系统。

  • As noted earlier, Subsystem is now an interface (Java, C++); the closest equivalent of the old Subsystem is the new SubsystemBase 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已被删除;子系统不再需要“知道”它们的默认命令,而是直接注册到CommandScheduler. 新的setDefaultCommand方法简单地包装CommandScheduler程序打电话。

  • 子系统不再“知道”当前需要它们的命令;这只由CommandScheduler. 然而,一个方便包装命CommandScheduler.提供了方法。

命令更改

备注

有关命令的更多信息,请参见:doc:commands.

  • As noted earlier, Command is now an interface (Java, C++); the closest equivalent of the old Command is the new CommandBase 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.

  • 命令不再处理自己的调度状态;现在这是调度程序的责任。

  • ``interrupted()’’方法已经被卷入到``end()``方法中,该方法现在使用一个参数来指定命令是否被中断(如果正常结束则为``false’’)。

  • requires()``方法已重命名为``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 subclass Foo must extend CommandHelper<Foo, Base> where Base is the desired base class.

PIDS子系统/ PIDCommand的变化

备注

更多的信息,请参见:doc:pid-subsystems-commands, and WPILib中的PID控制

  • 在对PIDController进行更改之后,这些类现在可以从机器人主循环中同步运行。

  • l  这个PIDController现在通过构造函数注入,删除许多转发方法,构筑后后可以改建为getController().

  • 如GyroDriveCommands示例(Java <https://github.com/wpilibsuite/allwpilib/tree/main/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/gyrodrivecommands>`__,C ++)所示,PIDCommand主要用于内联使用。

  • 如果用户希望更“传统地”使用PIDCommand,则已覆盖的受保护的“ returnPIDInput()”和“ usePIDOutput(double output)”方法已被修改为受保护的“ m_measurement”和“ m_useOutput”领域。同样,用户可以调用受保护的m_setpoint字段,而不用调用setSetpoint。