Files
allwpilib/wpilibj/src/main/java/org/wpilib/opmode/OpMode.java

85 lines
3.6 KiB
Java
Raw Normal View History

// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package org.wpilib.opmode;
import java.util.Set;
import org.wpilib.framework.OpModeRobot;
import org.wpilib.internal.PeriodicPriorityQueue;
/**
* Top-level interface for opmode classes. Users should generally extend one of the abstract
[wpilib] Remove LinearOpMode (#8638) Linear OpModes have several major downsides with no obvious solutions: - Some things stop working automatically--e.g. in a linear opmode, simulation will not work out-of-the-box; the user must explicitly call sim themselves.  there's a few other things we do periodically, but this is the big one (it also forces some decisions on other parts of the library—eg if we want Tunable to work in linear without the user manually calling refresh, we have to run it on a background thread, which means it must be thread safe throughout).  We can help in some areas (e.g. have sleep functions call background things), but if the user is writing a loop that waits to drive a certain distance with no sleep, it's an easy footgun - Writing code with no sleeps is easy to do, and can hog an entire processing core easily--yes, there's more than one core, but it could still easily impact e.g. vision processing - Many people I've talked to want robot-level periodic and periodic sim functions.  Given linear opmodes, we have two options, neither of which is great: (1) don't provide robot-level periodic functions, and the users who want those must set those up themselves and remember to call them explicitly from every periodic opmode, or (2) provide them, but only call them automatically from periodic opmodes, which could be confusing for linear opmode users (they'd have to call them manually if they wanted them).  Currently we do (1) but someone in the community already opened a change to do (2). - Restarting the robot program fixes the "stuck in auto for the rest of the match" problem but still feels like an ugly hack because the startup time is not unlikely to make the robot not immediately ready for teleop Removing LinearOpMode resolves these issues by moving to a periodic-only structure. We can address the few notable use cases of LinearOpMode (e.g. very basic autonomous sequences) in other ways such as Blocks generated code, better state machine tutorials/documentation, etc.
2026-02-27 14:26:27 -08:00
* implementations of this interface (e.g. {@link PeriodicOpMode}) rather than directly implementing
* this interface.
*
* <p><b>Lifecycle</b>:
*
* <ul>
* <li>constructed when opmode selected on driver station
* <li>disabledPeriodic() called periodically as long as DS is disabled. Note this is not called
* on a set time interval (it does not use the same time interval as periodic())
* <li>when DS transitions from disabled to enabled, start() is called once
* <li>while DS is enabled, periodic() is called periodically at {@link OpModeRobot#getPeriod},
* and additional periodic callbacks added via addPeriodic() are called periodically on their
* set time intervals
* <li>when DS transitions from enabled to disabled, or a different opmode is selected on the
* driver station when the DS is enabled, end() is called, followed by close(); the object is
* not reused
* <li>if a different opmode is selected on the driver station when the DS is disabled, only
* close() is called; the object is not reused
* </ul>
*
* <p>All lifecycle callbacks and periodic callbacks run synchronously on the same thread that
* invokes them. Interactions between opmodes and the robot framework do not require additional
* synchronization.
*
* <p>Additional callbacks can be registered by implementing {@link #getCallbacks()} to return a set
* of {@link PeriodicPriorityQueue.Callback} objects with custom timing. {@link PeriodicOpMode}
* provides a convenient implementation of this method and utility methods for adding periodic
* callbacks.
*/
public interface OpMode extends AutoCloseable {
/**
* This function is called periodically while the opmode is selected and the robot is disabled.
* Code that should only run once when the opmode is selected should go in the opmode constructor.
*/
default void disabledPeriodic() {}
/** Called once when this opmode transitions to enabled. */
default void start() {}
/**
* This function is called periodically while the opmode is enabled at the rate returned by {@link
* OpModeRobot#getPeriod()}.
*/
default void periodic() {}
/**
* This function is called asynchronously when the robot disables or switches opmodes while this
* opmode is enabled. Implementations should stop blocking work promptly.
*/
default void end() {}
/**
* This function is called when the opmode is no longer selected on the DS or after an enabled run
* ends. The object will not be reused after this is called.
*/
@Override
default void close() {}
/**
* Returns a set of custom periodic callbacks to be executed while the opmode is enabled.
*
* <p>This method allows opmodes to register arbitrary periodic callbacks with custom execution
* intervals. The callbacks are executed by the robot framework at their scheduled times, in
* addition to the primary {@link #periodic()} callback.
*
* @return A set of custom callbacks to execute, or an empty set if no custom callbacks are
* needed. The default implementation returns an empty set.
*/
default Set<PeriodicPriorityQueue.Callback> getCallbacks() {
return Set.of();
}
}