From ecea4beac46c1de747cacedcc2716f74ce83b46e Mon Sep 17 00:00:00 2001 From: Daniel1464 Date: Sat, 23 May 2026 11:54:55 -0400 Subject: [PATCH 1/5] initial --- src/config/sidebarConfig.ts | 11 ++ .../the-command-scheduler.mdx | 33 +++++ .../docs/section-2-commands/why-commands.mdx | 113 ++++++++++++++ .../section-2-commands/why-mechanisms.mdx | 140 ++++++++++++++++++ src/styles/global.css | 5 + 5 files changed, 302 insertions(+) create mode 100644 src/content/docs/section-2-commands/the-command-scheduler.mdx create mode 100644 src/content/docs/section-2-commands/why-commands.mdx create mode 100644 src/content/docs/section-2-commands/why-mechanisms.mdx diff --git a/src/config/sidebarConfig.ts b/src/config/sidebarConfig.ts index 9642d0b..8d0161e 100644 --- a/src/config/sidebarConfig.ts +++ b/src/config/sidebarConfig.ts @@ -65,6 +65,17 @@ export const sidebarSections: Record = { }, ], + '/section-2-commands': [ + { + label: 'Section 2: Commands', + items: [ + { label: 'Why use Commands?', slug: 'section-2-commands/why-commands' }, + { label: 'Why use Mechanisms?', slug: 'section-2-commands/why-mechanisms' }, + { label: 'The Command Scheduler', slug: 'section-2-commands/the-command-scheduler' }, + ], + } + ] + // Resources section (content lives at /resources but navbar says "Other Resources") // '/resources': [ // { diff --git a/src/content/docs/section-2-commands/the-command-scheduler.mdx b/src/content/docs/section-2-commands/the-command-scheduler.mdx new file mode 100644 index 0000000..167a976 --- /dev/null +++ b/src/content/docs/section-2-commands/the-command-scheduler.mdx @@ -0,0 +1,33 @@ +--- +title: The Command Scheduler +description: How to use the command scheduler +prev: section-2-commands/why-mechanisms +next: false +--- +import Aside from '../../../components/Aside.astro'; + +# The Command Scheduler + +Commands within commands v3 are run and handled by the command scheduler. +The command scheduler can be fetched via ```Scheduler.getDefault()```. + +In order for commands to work, you must call ```Scheduler.getDefault().run()``` +periodically, in the ```robotPeriodic``` method of your robot class. This will work +with robot classes that extend ```TimedRobot``` and ```OpModeRobot```. + +```java +public class Robot extends TimedRobot { + @Override + public void robotPeriodic() { + Scheduler.getDefault().run(); + } +} +``` + + + diff --git a/src/content/docs/section-2-commands/why-commands.mdx b/src/content/docs/section-2-commands/why-commands.mdx new file mode 100644 index 0000000..a039bf4 --- /dev/null +++ b/src/content/docs/section-2-commands/why-commands.mdx @@ -0,0 +1,113 @@ +--- +title: Why Commands +description: The what, how, and why of commands +prev: false +next: section-2-commands/why-mechanisms +--- +import Aside from '../../../components/Aside.astro'; + +# What is a Command? + +A command is an action a robot can take - which can include something as simple +as raising an arm joint or complex as an autonomous program. Think of them as powered-up +methods that can handle the requirements for controlling a robot over long periods of time. + +# What's wrong with methods? + +Let's say you're writing a method that prints "hello world!" to the console, +then sets a motor to 5 volts indefinitely. Your first instinct might be to do this: +```java +public void printHiAndRunMotor() { + System.out.println("Hello World!"); + while (true) { + motor.setVoltage(5.0); + } +} +``` +Here, the problem is with the while loop. While it's running, we are only setting the voltage of the motor; +not listening to button presses, logging data, and running other background tasks. To function properly, WPILib +requires many of these background tasks to be run periodically(at a 0.02 second or smaller interval). + +## Enter: Commands! + +Functionally, commands are basically superpowered methods that allow you to run the required background +tasks described in the previous section, ensuring that WPILib functions properly when a while loop is running. +This is done by calling ```coroutine.yield()``` inside of a while loop, like so: +```java +while (true) { + motor.setVoltage(5.0); + coroutine.yield(); +} +``` + + + +# Command Syntax + +A fully constructed command looks like this: +```java +Command runMotor = + Command.noRequirements(coroutine -> { + System.out.println("Hello World!"); + while (true) { + motor.setVoltage(5.0); + coroutine.yield(); + } + }) + .named("Set to 5 volts"); +``` + +There's a lot to digest here, so let's break it down step-by-step. +- Even though commands are more like methods, they act like objects in java. +Hence, the ```Command runMotor``` definition. +- ```Command.noRequirements``` creates the command. +We'll explain what "noRequirements" means in the following section. +- Every line of code between ```coroutine -> {``` and ```}``` will be run +when the command runs: just like a method body. +- ```named("Set to 5 Volts")``` gives the command a name, which allows programmers +to distinguish this command from others when using debugging tools. + +# Running Commands + +The following allows you to start a command asynchronously: + +```java +Command runMotor = ...; // see previous example +Scheduler.getDefault().schedule(runMotor); +System.out.println("Hello!"); +``` + +Think of calling ```schedule()``` as ordering a robot to start washing the dishes +without waiting for it to finish. In this case, the ```println("Hello!")``` statement +will run before the ```runMotor``` command completes. + +But the vast majority of the time, you want a command to run when a button is pressed or held down. +To do this, we use a ```CommandGamepad``` instead of a ```Gamepad```, like so: +```java +private CommandGamepad xbox = new CommandGamepad(0); + +public Robot() { + xbox.leftTrigger().onTrue(runMotor); +} +``` + +In this case, the ```runMotor``` command will run once the left trigger is pressed. +If it is desired to cancel the runMotor command once the left trigger is released, +the ```onTrue``` statement can be replaced with ```whileTrue```: +```java +public Robot() { + driverController.leftTrigger().whileTrue(runMotor); +} +``` + +Generally, whileTrue is desireable over onTrue since it provides a way for a driver/operator +to quickly cancel a command if it goes awry. + + + + + + diff --git a/src/content/docs/section-2-commands/why-mechanisms.mdx b/src/content/docs/section-2-commands/why-mechanisms.mdx new file mode 100644 index 0000000..ec2c43f --- /dev/null +++ b/src/content/docs/section-2-commands/why-mechanisms.mdx @@ -0,0 +1,140 @@ +--- +title: Mechanisms in Command-Based Programming +description: Why we need mechanisms in command-based +prev: section-2-commands/why-commands +next: section-2-commands/the-command-scheduler +--- +import Aside from '../../../components/Aside.astro'; + +# An overview of Mechanisms + +A ```Mechanism```, on the surface level, is a part of the robot, like a double-jointed arm or a shooter. +If you've used commands V2 before, they're the exact same thing as subsystems (and in that case, feel free +to skip to the "Defining a Mechanism" section). + +# Conflicting Commands + +Let's say we have the following code: + +```java +CommandGamepad driverController = new CommandGamepad(0); +Command shootAt5Volts = ...; // assume we have a command defined here. +Command shootAt7Volts = ...; // same here. +driverController.leftTrigger().whileTrue(shootAt5Volts); +driverController.rightTrigger().whileTrue(shootAt7Volts); +``` + +When we hold down the left trigger, the shooter is ran at 5 volts, and when +we hold down the right trigger, it's set to 7 volts. Pretty simple. + +Notice here, though, that it's possible for both triggers to be held down at the same time, +which would cause ```shootAt5Volts``` and ```shootAt7Volts``` to run simultaneously. This is obviously +undefined behavior that we want to prevent - but how? + +# Using Mechanisms to fix conflicting commands + +Ideally, we could declare what motors each command requires. If 2 commands that +required the same motor were ran simultaneously, one would get cancelled. + +However, there are many varieties of motors and actuating components. As a result, the commands +v3 framework leaves it to the coder to group these motors/components into categories, called mechanisms. +Each command will then declare the mechanisms they require. + +For instance, the 4 motors that control a robot's movement on the field could be grouped into a "drivetrain" mechanism. +If we were to declare a command that drives the robot forward by 5 meters, it would require this drivetrain mechanism. + +# Defining a Mechanism + +Mechanisms are represented as classes in java, inside their own separate files. +Note that a mechanism class slightly deviates from a traditional class with the ```implements Mechanism``` keyword at the end. + +```java +public class Arm implements Mechanism { + private final TalonFX motor = new TalonFX(4); +} +``` + +Then, in the ```Robot.java``` file, you would simply define an instance of each mechanism like so: +```java +public class Robot { + private final Arm arm = new Arm(); +} +``` + +# Defining commands that require a mechanism + +In general, commands that require a mechanism should be defined inside of that mechanism's class. +If that approach is followed, you can create a command that requires the arm mechanism like so: + +```java +public class Arm implements Mechanism { + private final TalonFX motor = new TalonFX(4); + + public Arm() { + Command move = + run(coroutine -> { + while (true) { + motor.setVoltage(5,0); + coroutine.yield(); + } + }) + .named("Move Arm"); + } +} +``` + + + +However, this poses a problem: the ```move``` command isn't accessible to the Robot class, +since it only exists inside of the constructor of the Arm class. To remedy this, we +can instead make a method that creates an instance of the ```move``` command: + +```java +public class Arm implements Mechanism { + private final TalonFX motor = new TalonFX(4); + + public Command move() { + return run(coroutine -> { + while (true) { + motor.setVoltage(5,0); + coroutine.yield(); + } + }) + .named("Move Arm"); + } +} +``` + +Then, in Robot.java, you can use that command like so: + +```java +public class Robot { + private final CommandGamepad xbox = new CommandGamepad(0); + private final Arm arm = new Arm(); + + public Robot() { + xbox.leftTrigger().whileTrue(arm.move()); + } +} +``` + + \ No newline at end of file diff --git a/src/styles/global.css b/src/styles/global.css index 3997005..3960195 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -746,3 +746,8 @@ html.sidebar-collapsed .sidebar-collapsed-toggle-wrapper { margin-bottom: 1rem; text-align: center; } + +.code { + margin-left: 0; + margin-right: auto; +} \ No newline at end of file From 971f19692325daebe8347aa454ad229d4b4bb51a Mon Sep 17 00:00:00 2001 From: Daniel1464 Date: Sat, 23 May 2026 11:58:47 -0400 Subject: [PATCH 2/5] minor clarity fixes --- src/content/docs/section-2-commands/why-commands.mdx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/content/docs/section-2-commands/why-commands.mdx b/src/content/docs/section-2-commands/why-commands.mdx index a039bf4..4b28a1b 100644 --- a/src/content/docs/section-2-commands/why-commands.mdx +++ b/src/content/docs/section-2-commands/why-commands.mdx @@ -89,7 +89,8 @@ To do this, we use a ```CommandGamepad``` instead of a ```Gamepad```, like so: ```java private CommandGamepad xbox = new CommandGamepad(0); -public Robot() { +public Robot() { + Command runMotor = ...; xbox.leftTrigger().onTrue(runMotor); } ``` @@ -99,6 +100,7 @@ If it is desired to cancel the runMotor command once the left trigger is release the ```onTrue``` statement can be replaced with ```whileTrue```: ```java public Robot() { + Command runMotor = ...; driverController.leftTrigger().whileTrue(runMotor); } ``` From 5fa2de00f46b730373410eee0b65927468d8c3d8 Mon Sep 17 00:00:00 2001 From: Daniel1464 Date: Sat, 23 May 2026 21:46:32 -0400 Subject: [PATCH 3/5] replace arm with shooter --- .../docs/section-2-commands/why-commands.mdx | 7 ++-- .../section-2-commands/why-mechanisms.mdx | 40 +++++++++---------- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/src/content/docs/section-2-commands/why-commands.mdx b/src/content/docs/section-2-commands/why-commands.mdx index 4b28a1b..131a20a 100644 --- a/src/content/docs/section-2-commands/why-commands.mdx +++ b/src/content/docs/section-2-commands/why-commands.mdx @@ -30,15 +30,16 @@ requires many of these background tasks to be run periodically(at a 0.02 second ## Enter: Commands! -Functionally, commands are basically superpowered methods that allow you to run the required background -tasks described in the previous section, ensuring that WPILib functions properly when a while loop is running. -This is done by calling ```coroutine.yield()``` inside of a while loop, like so: +Functionally, commands are superpowered methods that gives you a special statement that runs +these background tasks within a while loop: ```coroutine.yield()```. ```java +System.out.println("Hello World!"); while (true) { motor.setVoltage(5.0); coroutine.yield(); } ``` +In other words, it "yields control" to any pending background tasks before resuming the while loop. -However, this poses a problem: the ```move``` command isn't accessible to the Robot class, -since it only exists inside of the constructor of the Arm class. To remedy this, we -can instead make a method that creates an instance of the ```move``` command: +However, this poses a problem: the ```shoot``` command isn't accessible to the Robot class, +since it only exists inside of the constructor of the Shooter class. To remedy this, we +can instead make a method that creates an instance of the ```shoot``` command: ```java -public class Arm implements Mechanism { +public class Shooter implements Mechanism { private final TalonFX motor = new TalonFX(4); - public Command move() { + public Command shoot() { return run(coroutine -> { while (true) { motor.setVoltage(5,0); coroutine.yield(); } }) - .named("Move Arm"); + .named("Shoot"); } } ``` @@ -113,28 +113,28 @@ Then, in Robot.java, you can use that command like so: ```java public class Robot { private final CommandGamepad xbox = new CommandGamepad(0); - private final Arm arm = new Arm(); + private final Shooter shooter = new Shooter(); public Robot() { - xbox.leftTrigger().whileTrue(arm.move()); + xbox.leftTrigger().whileTrue(shooter.shoot()); } } ``` \ No newline at end of file From 91e49217901674c69f8b49dff5b418e429031756 Mon Sep 17 00:00:00 2001 From: Daniel1464 Date: Sat, 23 May 2026 22:06:54 -0400 Subject: [PATCH 4/5] Change triple quotes to single quotes for inline code blocks --- .../docs/section-2-commands/why-commands.mdx | 24 +++++++++---------- .../section-2-commands/why-mechanisms.mdx | 20 ++++++++-------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/content/docs/section-2-commands/why-commands.mdx b/src/content/docs/section-2-commands/why-commands.mdx index 131a20a..251ae03 100644 --- a/src/content/docs/section-2-commands/why-commands.mdx +++ b/src/content/docs/section-2-commands/why-commands.mdx @@ -31,7 +31,7 @@ requires many of these background tasks to be run periodically(at a 0.02 second ## Enter: Commands! Functionally, commands are superpowered methods that gives you a special statement that runs -these background tasks within a while loop: ```coroutine.yield()```. +these background tasks within a while loop: `coroutine.yield()`. ```java System.out.println("Hello World!"); while (true) { @@ -42,7 +42,7 @@ while (true) { In other words, it "yields control" to any pending background tasks before resuming the while loop. @@ -63,12 +63,12 @@ Command runMotor = There's a lot to digest here, so let's break it down step-by-step. - Even though commands are more like methods, they act like objects in java. -Hence, the ```Command runMotor``` definition. -- ```Command.noRequirements``` creates the command. +Hence, the `Command runMotor` definition. +- `Command.noRequirements` creates the command. We'll explain what "noRequirements" means in the following section. -- Every line of code between ```coroutine -> {``` and ```}``` will be run +- Every line of code between `coroutine -> {` and `}` will be run when the command runs: just like a method body. -- ```named("Set to 5 Volts")``` gives the command a name, which allows programmers +- `named("Set to 5 Volts")` gives the command a name, which allows programmers to distinguish this command from others when using debugging tools. # Running Commands @@ -81,12 +81,12 @@ Scheduler.getDefault().schedule(runMotor); System.out.println("Hello!"); ``` -Think of calling ```schedule()``` as ordering a robot to start washing the dishes -without waiting for it to finish. In this case, the ```println("Hello!")``` statement -will run before the ```runMotor``` command completes. +Think of calling `schedule()` as ordering a robot to start washing the dishes +without waiting for it to finish. In this case, the `println("Hello!")` statement +will run before the `runMotor` command completes. But the vast majority of the time, you want a command to run when a button is pressed or held down. -To do this, we use a ```CommandGamepad``` instead of a ```Gamepad```, like so: +To do this, we use a `CommandGamepad` instead of a `Gamepad`, like so: ```java private CommandGamepad xbox = new CommandGamepad(0); @@ -96,9 +96,9 @@ public Robot() { } ``` -In this case, the ```runMotor``` command will run once the left trigger is pressed. +In this case, the `runMotor` command will run once the left trigger is pressed. If it is desired to cancel the runMotor command once the left trigger is released, -the ```onTrue``` statement can be replaced with ```whileTrue```: +the `onTrue` statement can be replaced with `whileTrue`: ```java public Robot() { Command runMotor = ...; diff --git a/src/content/docs/section-2-commands/why-mechanisms.mdx b/src/content/docs/section-2-commands/why-mechanisms.mdx index 53e294f..5dcaafd 100644 --- a/src/content/docs/section-2-commands/why-mechanisms.mdx +++ b/src/content/docs/section-2-commands/why-mechanisms.mdx @@ -8,7 +8,7 @@ import Aside from '../../../components/Aside.astro'; # An overview of Mechanisms -A ```Mechanism```, on the surface level, is a part of the robot, like a double-jointed arm or a shooter. +`Mechanism`, on the surface level, is a part of the robot, like a double-jointed arm or a shooter. If you've used commands V2 before, they're the exact same thing as subsystems (and in that case, feel free to skip to the "Defining a Mechanism" section). @@ -28,7 +28,7 @@ When we hold down the left trigger, the shooter is ran at 5 volts, and when we hold down the right trigger, it's set to 7 volts. Pretty simple. Notice here, though, that it's possible for both triggers to be held down at the same time, -which would cause ```shootAt5Volts``` and ```shootAt7Volts``` to run simultaneously. This is obviously +which would cause `shootAt5Volts` and `shootAt7Volts` to run simultaneously. This is obviously undefined behavior that we want to prevent - but how? # Using Mechanisms to fix conflicting commands @@ -46,7 +46,7 @@ If we were to declare a command that drives the robot forward by 5 meters, it wo # Defining a Mechanism Mechanisms are represented as classes in java, inside their own separate files. -Note that a mechanism class slightly deviates from a traditional class with the ```implements Mechanism``` keyword at the end. +Note that a mechanism class slightly deviates from a traditional class with the `implements Mechanism` keyword at the end. ```java public class Shooter implements Mechanism { @@ -54,7 +54,7 @@ public class Shooter implements Mechanism { } ``` -Then, in the ```Robot.java``` file, you would simply define an instance of each mechanism like so: +Then, in the `Robot.java` file, you would simply define an instance of each mechanism like so: ```java public class Robot { private final Shooter shooter = new Shooter(); @@ -84,13 +84,13 @@ public class Shooter implements Mechanism { ``` -However, this poses a problem: the ```shoot``` command isn't accessible to the Robot class, +However, this poses a problem: the `shoot` command isn't accessible to the Robot class, since it only exists inside of the constructor of the Shooter class. To remedy this, we -can instead make a method that creates an instance of the ```shoot``` command: +can instead make a method that creates an instance of the `shoot` command: ```java public class Shooter implements Mechanism { @@ -122,8 +122,8 @@ public class Robot { ```