Skip to content

Commit

Permalink
Command scheduler and YPP
Browse files Browse the repository at this point in the history
  • Loading branch information
bovlb committed Aug 9, 2023
1 parent 2aca9fd commit 0a0512b
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 6 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ This project is a small collection of tips I've gathered to save redoing the sam
* [Coast mode](coast-mode/): How do I make my robot stop, stay stopped, and yet be easy to move?
* [Burnout](burnout/): How do you stop your motors from burning out?
* [Safety Captain](safety/): Help! I just got appointed Safety Captain. What do I do now?
* [Commands](commands/): Short guide to WPILIB commands, including [lambda functions](commands/lambda.md)
* [Commands](commands/): Short guide to WPILIB commands, including [lambda functions](commands/lambda.md), and [CommandScheduler](commands/commandscheduler.md)
* [Links](links/): What are some useful resources for FRC?

I decided to put this together as a Github repository, partly so I could incorporate code files if I needed to, but mostly to make it easier for others to correct my inevitable mistakes.
Expand Down
10 changes: 5 additions & 5 deletions commands/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Commands

Although you can avoid it in some system cases, doing anything complex with your FRC robot will involve creating commands. These respond to joysticks and buttons, run your autoonomous routines, and do other maintenance tasks.
Although you can avoid it in some simple cases, doing anything complex with your FRC robot will involve creating commands. These respond to joysticks and buttons, run your autoonomous routines, and do other maintenance tasks.

In addition to the usual constructor, commands have four lifecycle methods: [`initialize`](#void-initialize), [`execute`](#void-execute), [`isFinished`](#boolean-isfinished), and [`end`](#void-endboolean-interrupted). These methods are called by the scheduler (and never by you). By overriding the implementation of these methods, you can change the behaviour of the command.
In addition to the usual constructor, commands have four lifecycle methods: [`initialize`](#void-initialize), [`execute`](#void-execute), [`isFinished`](#boolean-isfinished), and [`end`](#void-endboolean-interrupted). These methods are called by the [command scheduler](commandscheduler.md) (and never by you). By overriding the implementation of these methods, you can change the behaviour of the command.

<figure style="float: right; width: 50%;"><img style="width: 100%" src="lifecycle.png" alt="Lifecycle methods of a command: initialize, execute, isFinished, and end" />
<figcaption>The scheduler calls the four lifecycle methods of a command. This starts with <tt>initialize</tt> when the command is first scheduled, then <tt>execute</tt> and <tt>isFinished</tt> are called in alternation. Finally <tt>end</tt> is called either when <tt>isFinished</tt> returns trure, or when the command is interrupted.</figcaption>
Expand Down Expand Up @@ -46,7 +46,7 @@ These might seem a little complex and daunting, but the good news is that if you

<figure style="float: right; width: 50%;" >
<img style="width: 100%;" src="commandgroups.png" alt="Diagram showing SequentialCommandGroup, ParallelCommandGroup, ParallelRaceGroup and ParallelDeadlineGroup" />
<figcaption><tt>SequentialCommandGroup</tt> runs each command in turn until the last finishs. <tt>ParallelCommandGroup</tt> runs the commands in parallel, until they all finish. <tt>ParallelRaceGroup</tt> runs until the fastest command finishes. <tt>ParallelDeadlineGroup</tt> runs until the first command finishes.</figcaption>
<figcaption><tt>SequentialCommandGroup</tt> runs each command in turn until the last finishes. <tt>ParallelCommandGroup</tt> runs the commands in parallel, until they all finish. <tt>ParallelRaceGroup</tt> runs until the fastest command finishes. <tt>ParallelDeadlineGroup</tt> runs until the first command finishes.</figcaption>
</figure>

These classes group togather one or more commands and execute them all in some order. They inherit the subsystem requirements of all of their sub-commands. The sub-commands can be specified either in the constructor, or by subclassing and using `addCommands`.
Expand Down Expand Up @@ -76,7 +76,7 @@ The following commands are useful to build command groups. Some of them take co

* `ConditionalCommand`: Given a condition (evaluated in `initialize`), runs one of two sub-commands. See also the decorator `unless`.
* `SelectCommand`: Takes a mapping from keys to commands, and a key selector. At `initialize`, the key selector is executed and then one of the sub-commands is run.
* `ProxyCommand`: This behaves exactly like the underlying command except that subsystem requirements are not inherited. See also the decorator `asProxy`.
* `ProxyCommand`: This behaves exactly like the underlying command except that subsystem requirements are not shared between the child and parent commands. See also the decorator `asProxy`. **Warning**: `ProxyCommand` works by scheduling the command independently and waiting for it to complete. A consequence of this is that any scheduled commands with overlapping requirements will be interrupted. If this includes the command group that is using `ProxyCommand`, then the proxy command will also be canceled.
* `RepeatCommand`: Run the sub-command until it is finished, and then start it running again. See also the decorator `repeatedly`.
* `WaitCommand`: Insert a delay for a specific time.
* `WaitUntilCommand`: Insert a delay until some condition is met.
Expand Down Expand Up @@ -139,7 +139,7 @@ new Trigger(() -> subsystem.getLimitSwitch()).whileTrue(...)

<figure style="float: right; width: 50%;">
<img style="width: 100%" src="triggers.png" alt="Comparison of onFalse, onTrue, toggleOnFalse, toggleOnTrue, whilefalse, and whileTrue" />
<figcaption><tt>onTrue</tt> starts when a button is pressed and usually ends on its own. <tt>whileTrue</tt> wtarts when the button is pressed and runs until it is released. <tt>toggleOnTrue</tt> turns on or off in alternation every time the button is pressed. <tt>onFalse</tt>, <tt>whileFalse</tt>, and <tt>toggleOnFalse</tt> do the same, but when the button is released.</figcaption>
<figcaption><tt>onTrue</tt> starts when a button is pressed and usually ends on its own. <tt>whileTrue</tt> starts when the button is pressed and runs until it is released. <tt>toggleOnTrue</tt> turns on or off in alternation every time the button is pressed. <tt>onFalse</tt>, <tt>whileFalse</tt>, and <tt>toggleOnFalse</tt> do the same, but when the button is released.</figcaption>
</figure>

Some trigger methods should be passed a command to run:
Expand Down
36 changes: 36 additions & 0 deletions commands/commandscheduler.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# CommandScheduler

When you are first taught to program, you are usually shown what is called the "imperative" style. That means that you are in control of what happens when. In a command-based robot, you have to use an "event-driven" style. You must learn how to break your code up into small pieces that execute quickly and rely on the `CommandScheduler` to call them at the right time. The `CommandScheduler` will manage commands, calling their four lifecycle methods (`initialize`, `execute`, `isFinished`, `end`). It will also call the `periodic` methods of your subsystems and test any triggers you may have (mostly this will be joystick buttons). It is also responsible for managing the requirements of two commands, so two commands with overlapping requirements are never scheduled at the same time.

There are a number of ways to invoke the `CommandScheduler`:

## `CommandScheduler.getInstance().run()`
* This makes the `CommandScheduler` perform its main loop for subsystems, triggers, and commands.
* This should be called from `Robot.robotPeriodic` and nowhere else.
* Most commands will not run while the robot is disabled, so will be automatically cancelled.

## `Trigger` methods
* When you set up a `Trigger` with a `Command`, then the `CommandScheduler` will automatically test the trigger. When the trigger activates, it will call `schedule` on the command.
* You're probably already using `Trigger`s in the form of joystick buttons.

## `Command.schedule()`
* Attempts to add the command to the list of scheduled commands.
* If a scheduled command has overlapping requirements, then either the other commands will be cancelled or if the other commands are non-interruptible (rare), then the attempt will fail.
* This should be called by `Robot.automomousInit` to set the autonomous command.
* It's fairly rare for teams to call `schedule` in any other context. The main example is a pattern where you create a state machine by having each state be a separate command, with all of them sharing the same requirements. Outside that, if you find yourself wanting to call this anywhere else, you're probably doing something wrong.
* Calls to `schedule` from inside a command lifecycle method are deferred until after all the scheduled commands have been run.

## `Command.cance()`
* Unschedules the command
* May cause a default command to be scheduled
* It is common to call `cancel` on the autonomous command inside `Robot.teleopInit`.
* There is also `CommandScheduler.getInstance().cancelAll
* Calls to `cancel` from inside a command lifecycle method are deferred until after all the scheduled commands have been run, and after all the pending schedules have been scheduled.
* It's pretty rare to have to call this. If you find yourself wanting to call this anywhere else, you're probably doing something wrong.

## See also
* https://docs.wpilib.org/en/stable/docs/software/commandbased/command-scheduler.html

<figure style="width: 100%;"><img style="width: 100%" src="commandscheduler.png" alt="Workflow of CommandScheduler" />
<figcaption>This shows the workflow of the CommandScheduler in Java. The C++ implemention has almost identical behaviour. This diagram dooes not show command event methods</figcaption>
</figure>
Binary file added commands/commandscheduler.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 0a0512b

Please sign in to comment.