命令调度程序

``CommandScheduler’’(Java <https://first.wpi.edu/wpilib/allwpilib/docs/release/java/edu/wpi/first/wpilibj2/command/CommandScheduler.html>`__,C ++)是负责实际运行命令的类。每次迭代(通常每20毫秒一次),调度程序都会轮询所有已注册的按钮,调度要执行的命令,运行所有已调度命令的命令主体,并结束已完成或被中断的命令。

“CommandScheduler”还运行每个已注册“Subsystem”的“periodic()”方法。

使用命令调度程序

“CommandScheduler” 是一个 单例类 ,这意味着它是一个只有一个实例的全局类。因此,为了访问调度程序,用户必须调用 “CommandScheduler.getInstance()” 命令。

在大多数情况下,用户不必直接调用调度程序方法——几乎所有重要的调度程序方法在其他位置都有方便包装器(例如,在“Command”和“Subsystem”接口中)。

但是,有一个例外:用户必须从其“Robot”类的“robotPeriodic()”方法中调用“CommandScheduler.getInstance().run()”。如果不这样做,则调度程序将永远不会运行,并且命令框架将无法运行。提供的基于命令的项目模板已包含此调用。

“schedule()”方法

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

为了安排命令,用户调用schedule()方法(Java <https://first.wpi.edu/wpilib/allwpilib/docs/release/java/edu/wpi/first/wpilibj2/command/CommandScheduler.html#schedule(boolean,edu.wpi.first.wpilibj2.command.Command…)>`__,C ++。该方法接受命令(以及可选的关于该命令是否可中断的规范),并尝试将其添加到当前正在运行的命令列表中,等待它是否已在运行或是否满足要求(如果已添加),将调用其“ initialize()”方法。

调度程序运行顺序

注解

每个“Command”的“initialize()”方法都是在调度命令时调用的,而不必在调度程序运行时调用(除非该命令已绑定到按钮)。

Flow diagram that show the sequence of each individual command.

调度程序的run()方法(Java <https://first.wpi.edu/wpilib/allwpilib/docs/release/java/edu/wpi/first/wpilibj2/command/CommandScheduler.html#run()>`__,C ++)的单次迭代实际上是做什么的?下一节将介绍调度程序迭代的逻辑。

步骤1:运行子系统定期方法

首先,调度程序对每个已注册的“子系统”运行“periodic()”方法。

步骤2:轮询命令调度触发器

注解

有关触发器绑定如何工作的更多信息,请参阅:doc:binding-commands-to-triggers

其次,调度程序轮询所有已注册触发器的状态,以查看是否应调度已绑定到这些触发器的任何新命令。如果满足调度绑定命令的条件,则对命令进行调度并运行其“Initialize()”方法。

步骤3:运行/完成计划的命令

第三,调度程序调用每个当前调度的命令的“execute()”方法,然后通过调用“isFinished()”方法检查命令是否完成。如果命令已完成,则还将调用“end()”方法,并对该命令进行调度,并释放其所需的子系统。

请注意,此调用顺序是针对每个命令按顺序进行的——因此,一个命令可能会先调用其“end()”方法,而另一命令可能会调用其“execute()”方法。命令按计划的顺序处理。

步骤4:调度默认命令

最后,任何已注册的“子系统”都有其默认命令(如果有的话)。注意,此时将调用默认命令的“initialize()”方法。

禁用调度程序

可以通过调用“CommandScheduler.getInstance().disable()”来禁用调度程序。禁用时,调度程序的“schedule()”和“run()”命令将不执行任何操作。

可以通过调用“CommandScheduler.getInstance.()enable()”来重新启用调度程序。

命令事件方法

有时,希望调度程序在发生某些命令事件(初始化,执行或结束)时执行自定义操作。可以使用以下三种方法完成此操作:

onCommandInitialize

每当初始化命令时,onCommandInitialize方法(Java <https://first.wpi.edu/wpilib/allwpilib/docs/release/java/edu/wpi/first/wpilibj2/command/CommandScheduler.html#onCommandInitialize(java.util.function.Consumer)>`__,C ++)都会运行指定的操作。

onCommandExecute

每当执行命令时,onCommandExecute方法(Java <https://first.wpi.edu/wpilib/allwpilib/docs/release/java/edu/wpi/first/wpilibj2/command/CommandScheduler.html#onCommandExecute(java.util.function.Consumer)>`__,C ++)都会运行指定的操作。

onCommandFinish

onCommandFinish方法(Java <https://first.wpi.edu/wpilib/allwpilib/docs/release/java/edu/wpi/first/wpilibj2/command/CommandScheduler.html#onCommandFinish(java.util.function.Consumer)>`__,C ++)只要命令正常完成(即isFinished()方法返回true),就会运行指定的操作。

onCommandInterrupt

onCommandInterrupt``方法(Java <https://first.wpi.edu/wpilib/allwpilib/docs/release/java/edu/wpi/first/wpilibj2/command/CommandScheduler.html#onCommandInterrupt(java.util.function.Consumer)>`__,C ++)每当命令被中断时(即通过显式取消或由另一条共享其要求之一的命令)运行指定的操作。

这些方法的典型用例是,每当发生命令调度事件时,便在事件日志中添加标记,如SchedulerEventLogging示例项目(Java <https://github.com/wpilibsuite/allwpilib/tree/main/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/schedulereventlogging> __,C ++ <https://github.com/wpilibsuite/allwpilib/tree/main/wpilibcExamples/src/main/cpp/examples/SchedulerEventLogging> __)所示:

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