Skip to main content

The Scheduler model

The Scheduler model is quite simply really—it's just a fancy loop.

Okay, it's slightly more complicated than that, but that's what it is at it's very core.

Yeahhh okay, that's not as helpful as I thought. Anyway...

The Scheduler is a glorified loop

The Scheduler model is a loop that runs until the OpMode is stopped, and this loop is made up of a few different parts.

Listeners👂

👀 This is the juicy bit, these are the backbone of the Scheduler API. Or wait, are they more like limbs since they're what actually do things? Whatever, anyways, they run after beforeEach and before afterEach (🤯)

Listeners are objects which hold a condition which hook to and are updated every cycle of the Scheduler. They can be subscribed to to perform certain actions when certain events are in certain states.

yeah I know that was a mouthful, so here's a more practical example:

@Override
public void runOpMode() throws InterruptedException {
Listener listener = new Listener(() -> gamepad1.a);

listener.onRise(() -> System.out.println("A was pressed!"));
listener.onFall(() -> System.out.println("A was released!"));

listener.whileHigh(() -> System.out.println("A is being held!"));
listener.whileLow(() -> System.out.println("A is not being touched!"));

Scheduler.start(this);
}
tip

Because the above 4 methods return the Listener instance, it can actually chain these methods together, so you can actually do something like this:

listener.onRise(() -> ...)
.onFall(() -> ...);

Note: This is a very rough overview of the Listener concept; if you're confused or want more information, check out the Listeners page.

We created a Listener which checks if the a button was pressed, and then we subscribed to a few sub-conditions, i.e. onRise, onFall, whileHigh, and whileLow.

The onRise and onFall refer to rising and falling edge states (was just pressed and was just released), and the whileHigh and whileLow refer to the high and low states (is being held and is not being touched).

Again, the Listener is being updated every loop of the Scheduler, and is functionally equivalent to:

(Using normal OpMode)
private boolean gamepad1AWasJustPressed = false;

@Override
public void loop {
if (gamepad1.a && !gamepad1AWasJustPressed) { // onRise
System.out.println("A was pressed!");
gamepad1AWasJustPressed = true;
} else if (!gamepad1.a && gamepad1AWasJustPressed) { // onFall
System.out.println("A was released!");
gamepad1AWasJustPressed = false;
}

if (gamepad1.a) { // whileHigh
System.out.println("A is being held!");
} else { // whileLow
System.out.println("A is not being touched!");
}
}

(And this gets even cleaner with the Reforged Gamepad!

beforeEach

This is a block of code which runs at the very start of every loop.

I myself just use it to reset variables that need to be reset every loop, but you can use it for whatever you want I guess lol.

You can find an example of how to use this right here.

afterEach

This is beforeEach's evil twin. It runs at the very end of every loop. It's very useful for actions that you want to run every loop, like PIDs, driving, or telemetry.

Example here.