Commands
Why use commands? Commands allow you to organize your code much more efficiently than you could otherwise. They are an excellent alternative to finite state machines, but are a lot easier to create and modify, and can reach higher levels of complexity than a finite state machine can.
Parts of a Command
A command has four main components: isDone
, start
, update
, and stop
.
isDone
is checked every loop. If it ever evaluates totrue
, the command will stop running.start
is run once, when the command is scheduled. It is used for setting up starting states and doing other things that should only happen once.update
runs every loop, many times per second. Because of this, it is crucial that it never takes more than a trivial amount of time to execute. You should be extremely careful of looping or doing anything else that could take significant amounts of timestop
runs once when the command ends, and recieves a parameter of whether or not it was interrupted by a different command.
Additionally, it has two more properties:
interruptible
determines whether or not the command is able to be interrupted. A command is interrupted when another command is scheduled that requires a subsystem the command is using. If a command is not interruptible, then the new command will not run.subsystems
is a set of all the subsystems a command uses. This is used for determing when two commands requrie the same subsystem. This is passed to the constructor of most premade commands.
Creating Commands
There are two ways to create a command: a LambdaCommand
and by creating your own command class.
Lambda Commands
A lambda command is the main way to create a command in NextFTC. A lambda command can be created as follows:
val myLambdaCommand = LambdaCommand()
.setStart {
// Runs on start
}
.setUpdate {
// Runs on update
}
.setStop { interrupted ->
// Runs on stop
}
.setIsDone { true } // Returns if the commmand has finished
.setSubsystems(/* subsystems the command implements */)
.setInterruptible(true)
TIP
All functions are completely optional. You only need to call the ones you will use. They can be called in any order.
NOTE
See the LambdaCommand
reference for more information.
Commands as Classes
It is unlikely that you will need to use this very often, but you can also create a command as a class. This is useful for cases where you need to reuse your command a lot. An command can be created as a class as follows:
class MyCommand(override val subsystems: Set<Subsystem>): Command() {
override val isDone: Boolean
get() = false // Whether or not the command is done
override val interruptible = true // Whether or not the command can be interrupted
override fun start() {
// Executed when the command begins
}
override fun update() {
// Executed on every update of the command
}
override fun stop(interrupted: Boolean) {
// Executed when the command ends
}
}
Executing Commands
There are two ways to schedule a command.
You can either call:
val myCommand = MyCommand() // Or a LambdaCommand
CommandManager.scheduleCommand(myCommand)
Or just:
val myCommand = MyCommand() // Or a LambdaCommand
myCommand()
NOTE
See the Command
reference for more information.