Requirements and Priorities
In the previous example with the arm raising command, you would likely also have a command that lowers the arm. Let's imagine a situation in which the arm is actively raising. There are numerous different ways that you may want to schedule the lowering command. In some situations, you may want to lower the arm immediately, overriding the raising command. In others, you may want to wait until the raising command finishes before lowering the arm, but you may decide this after you scheduled the raising command (meaning you can't use a sequential composition, as described in a later section). You may also want to immediately lower the arm, but then immediately raise it again.
With the tools provided so far, it would be inconvenient and verbose to have to write a separate command for each of these scenarios. To solve this problem, Ivy provides requirements. Requirements are a way to specify that a given command uses certain objects or subsystems on your robot. In the above example, you would have the raising and lowering commands require the arm motor(s) or the arm subsystem if you've created a class. In general, a command can have any number of requirements, and a requirement can be any object.
By themselves, requirements are not very useful. However, when combined with priorities, they allow you to specify how commands that share requirements should interact. A priority is an integer that specifies how important a command is. The default priority is 0.
When you try to schedule a command with conflicting requirements with any currently scheduled commands, there are three types of behaviors that can occur:
- Interrupted Behavior: If all currently scheduled commands have a lower priority than the new,
conflicting command, this determines what happens to each currently scheduled command.
InterruptedBehavioris an enum with typesENDandSUSPEND.ENDmeans that each currently scheduled command will terminate and not be run again, whileSUSPENDmeans that the currently scheduled command will be suspended and continue when the conflicting command finishes. In both cases,end()will be called on each currently scheduled command. Defaults toEND. - Blocked Behavior: If any currently scheduled command has a higher priority than the new,
conflicting command, this determines what happens to the conflicting command.
BlockedBehavioris an enum with typesCANCELandQUEUE.CANCELmeans that the conflicting command will be canceled, whileQUEUEmeans that the conflicting command will be queued and run after the currently scheduled conflicting commands finish. Defaults toCANCEL. - Conflict Behavior: If the highest priority of all currently scheduled commands is equal to
the new conflicting command, this determines what happens to the new conflicting command.
ConflictBehavioris an enum with typesCANCEL,QUEUE, andOVERRIDE.CANCELmeans that the new conflicting command will not be scheduled,QUEUEmeans that the new conflicting command will be queued and run after the currently scheduled conflicting commands finish, andOVERRIDEmeans that the new conflicting command will interrupt the currently scheduled conflicting commands and run instead (note, this triggers theInterruptedBehaviorof the currently scheduled conflicting commands). Defaults toOVERRIDE.
Returning to our arm example, instead of creating separate commands for each of the scenarios, we can create a single command and modify its priority to handle each scenario.
Note that requirements are a completely optional feature, and you can use Ivy perfectly well without them. However, they are a powerful tool that can help you write simpler and safer code should you want to use them.
Last updated on