Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/config/sidebarConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,16 @@ export const sidebarSections: Record<string, SidebarSection[]> = {
},
],

'/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' },
],
}
]
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
]
],

// Intro To Java section
'/intro-to-java': [
{
Expand Down
33 changes: 33 additions & 0 deletions src/content/docs/section-2-commands/the-command-scheduler.mdx
Original file line number Diff line number Diff line change
@@ -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();
}
}
```

<Aside type="note">
If you use the ```CommandRobot``` class, you should call ```Scheduler.getDefault().run()```
by overriding the ```periodic()``` method of subclassed opmodes, instead of calling it
inside the robot class. Inline opmodes created by ```createXXXOpMode``` will run the command scheduler
by default.
</Aside>

116 changes: 116 additions & 0 deletions src/content/docs/section-2-commands/why-commands.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
---
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?
Copy link
Copy Markdown
Collaborator

@Adrianamm Adrianamm May 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it needs some explanation of what command based programming is to make the transition between intro to Java and FRC programming smoother. I also think that knowing what is Command Based programming as a concept, even if it's in simple terms, is important.
This introduction could also mention what WPILib is since it's sort of mentioned in #9 but it's never correctly explained.


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?
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about "Why not use methods?" because I think that's the question most new programmers might think. also "what's wrong" could sound like methods aren't supposed to be used in FRC programming


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).
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about

many of these background tasks to be run periodically, which means they run at 0.02 seconds or at a smaller interval


## Enter: Commands!

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!");
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

System.out.println isn't used for print outs in FRC but I think this is a good spot to introduce and use Driverstation.reportWarning()

while (true) {
motor.setVoltage(5.0);
coroutine.yield();
}
```
In other words, it "yields control" to any pending background tasks before resuming the while loop.

<Aside type="note">
Because `coroutine.yield()` can't be called outside of commands, it is highly discouraged
to use while loops outside of commands unless if you know what you're doing.
</Aside>

# 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
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would just put the previous code there instead so viewers don't have to keep scrolling up to reference it. In addition, you could put a comment like //code from previous example on top so viewers know where the code is coming from if that's helpful

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.
Copy link
Copy Markdown
Collaborator

@Adrianamm Adrianamm May 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
But the vast majority of the time, you want a command to run when a button is pressed or held down.
But the vast majority of the time, you want a command to run when a button on a controller is pressed or held down.

To do this, we use a `CommandGamepad` instead of a `Gamepad`, like so:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At this point, they don't know what a Gamepad is so it's probably not worth mentioning

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't they have to know it due to section 1a being about coding a kitbot?

```java
private CommandGamepad xbox = new CommandGamepad(0);

public Robot() {
Command runMotor = ...;
xbox.leftTrigger().onTrue(runMotor);
}
```

In this case, the `runMotor` command will run once the left trigger is pressed.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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 on the controller 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`:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would explain more on why that is the case

```java
public Robot() {
Command runMotor = ...;
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.






140 changes: 140 additions & 0 deletions src/content/docs/section-2-commands/why-mechanisms.mdx
Original file line number Diff line number Diff line change
@@ -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.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It also might help to briefly explain the connection between Commands and Mechanisms. Could be as simple as explaining how Mechanism use Commands to move a part of the robot. Like spinning a motor on a shooter to shot a ball.

If you've used commands V2 before, they're the exact same thing as subsystems (and in that case, feel free
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be worth putting that in a note rather than in a paragraph

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
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
However, there are many varieties of motors and actuating components. As a result, the commands
However, there are many varieties of motors and actuating components on a robot. 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 Shooter 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 Shooter shooter = new Shooter();
}
```

# 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 shooter mechanism like so:

```java
public class Shooter implements Mechanism {
private final TalonFX motor = new TalonFX(4);

public Shooter() {
Command shoot =
run(coroutine -> {
while (true) {
motor.setVoltage(5,0);
coroutine.yield();
}
})
.named("Shoot");
}
}
```

<Aside type="note">
Recall that a command without any requirements is defined with `Command.noRequirements()`
instead of `run()`.
</Aside>

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 Shooter implements Mechanism {
private final TalonFX motor = new TalonFX(4);

public Command shoot() {
return run(coroutine -> {
while (true) {
motor.setVoltage(5,0);
coroutine.yield();
}
})
.named("Shoot");
}
}
```

Then, in Robot.java, you can use that command like so:

```java
public class Robot {
private final CommandGamepad xbox = new CommandGamepad(0);
private final Shooter shooter = new Shooter();

public Robot() {
xbox.leftTrigger().whileTrue(shooter.shoot());
}
}
```

<Aside type="note">
Note here that the `shooter.shoot()` call, by itself, doesn't actually run the shooter!
In other words, this won't do anything at the beginning of teleop:
```java
public class Robot extends TimedRobot {
private final Shooter shooter = new Shooter();

@Override
public void teleopInit() {
shooter.shoot();
}
}
```
Rather, it creates a command that, when scheduled or bound to a trigger,
will run the desired action. The java compiler will throw a compile-time error
if it detects this mistake in your code.
</Aside>
Loading