001// Copyright (c) FIRST and other WPILib contributors.
002// Open Source Software; you can modify and/or share it under the terms of
003// the WPILib BSD license file in the root directory of this project.
004
005package org.wpilib.opmode;
006
007import java.util.Set;
008import org.wpilib.framework.OpModeRobot;
009import org.wpilib.internal.PeriodicPriorityQueue;
010
011/**
012 * Top-level interface for opmode classes. Users should generally extend one of the abstract
013 * implementations of this interface (e.g. {@link PeriodicOpMode}) rather than directly implementing
014 * this interface.
015 *
016 * <p><b>Lifecycle</b>:
017 *
018 * <ul>
019 *   <li>constructed when opmode selected on driver station
020 *   <li>disabledPeriodic() called periodically as long as DS is disabled. Note this is not called
021 *       on a set time interval (it does not use the same time interval as periodic())
022 *   <li>when DS transitions from disabled to enabled, start() is called once
023 *   <li>while DS is enabled, periodic() is called periodically at {@link OpModeRobot#getPeriod},
024 *       and additional periodic callbacks added via addPeriodic() are called periodically on their
025 *       set time intervals
026 *   <li>when DS transitions from enabled to disabled, or a different opmode is selected on the
027 *       driver station when the DS is enabled, end() is called, followed by close(); the object is
028 *       not reused
029 *   <li>if a different opmode is selected on the driver station when the DS is disabled, only
030 *       close() is called; the object is not reused
031 * </ul>
032 *
033 * <p>All lifecycle callbacks and periodic callbacks run synchronously on the same thread that
034 * invokes them. Interactions between opmodes and the robot framework do not require additional
035 * synchronization.
036 *
037 * <p>Additional callbacks can be registered by implementing {@link #getCallbacks()} to return a set
038 * of {@link PeriodicPriorityQueue.Callback} objects with custom timing. {@link PeriodicOpMode}
039 * provides a convenient implementation of this method and utility methods for adding periodic
040 * callbacks.
041 */
042public interface OpMode extends AutoCloseable {
043  /**
044   * This function is called periodically while the opmode is selected and the robot is disabled.
045   * Code that should only run once when the opmode is selected should go in the opmode constructor.
046   */
047  default void disabledPeriodic() {}
048
049  /** Called once when this opmode transitions to enabled. */
050  default void start() {}
051
052  /**
053   * This function is called periodically while the opmode is enabled at the rate returned by {@link
054   * OpModeRobot#getPeriod()}.
055   */
056  default void periodic() {}
057
058  /**
059   * This function is called asynchronously when the robot disables or switches opmodes while this
060   * opmode is enabled. Implementations should stop blocking work promptly.
061   */
062  default void end() {}
063
064  /**
065   * This function is called when the opmode is no longer selected on the DS or after an enabled run
066   * ends. The object will not be reused after this is called.
067   */
068  @Override
069  default void close() {}
070
071  /**
072   * Returns a set of custom periodic callbacks to be executed while the opmode is enabled.
073   *
074   * <p>This method allows opmodes to register arbitrary periodic callbacks with custom execution
075   * intervals. The callbacks are executed by the robot framework at their scheduled times, in
076   * addition to the primary {@link #periodic()} callback.
077   *
078   * @return A set of custom callbacks to execute, or an empty set if no custom callbacks are
079   *     needed. The default implementation returns an empty set.
080   */
081  default Set<PeriodicPriorityQueue.Callback> getCallbacks() {
082    return Set.of();
083  }
084}