diff --git a/lib/src/main/java/com/team2813/lib2813/robot/PeriodicRegistry.java b/lib/src/main/java/com/team2813/lib2813/robot/PeriodicRegistry.java new file mode 100644 index 00000000..1dad2b8b --- /dev/null +++ b/lib/src/main/java/com/team2813/lib2813/robot/PeriodicRegistry.java @@ -0,0 +1,42 @@ +/* +Copyright 2026 Prospect Robotics SWENext Club + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package com.team2813.lib2813.robot; + +import java.util.function.Consumer; + +/** + * Service for registering callbacks that need to run periodically. + * + *

>Subsystems can extend {@link com.team2813.lib2813.subsystems.ModularSubsystem} to get access + * to an instance of {@link PeriodicRegistry}. This will ensure that time spent in the periodic + * methods are associated with the subsystem. + */ +public interface PeriodicRegistry { + + /** + * Add a callback to run for each iteration of the event loop. + * + * @param callback The callback to run. + */ + void addPeriodic(Consumer callback); + + /** + * Add a callback to run in simulation mode for each iteration of the event loop. + * + * @param callback The callback to run. + */ + void addSimulationPeriodic(Consumer callback); +} diff --git a/lib/src/main/java/com/team2813/lib2813/robot/RobotState.java b/lib/src/main/java/com/team2813/lib2813/robot/RobotState.java new file mode 100644 index 00000000..72bac1e9 --- /dev/null +++ b/lib/src/main/java/com/team2813/lib2813/robot/RobotState.java @@ -0,0 +1,58 @@ +/* +Copyright 2026 Prospect Robotics SWENext Club + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package com.team2813.lib2813.robot; + +/** Provides APIs for getting the current state of the robot. */ +public interface RobotState { + + /** + * Determines if the Robot is currently enabled. + * + * @return {@code True} if the Robot is currently enabled by the Driver Station. + */ + boolean isEnabled(); + + /** + * Determines if the Robot is currently disabled. + * + * @return {@code True} if the Robot is currently disabled by the Driver Station. + */ + default boolean isDisabled() { + return !isEnabled(); + } + + /** + * Determines if the robot is currently in Autonomous mode as determined by the Driver Station. + * + * @return {@code True} if the robot is currently operating autonomously. + */ + boolean isAutonomous(); + + /** + * Determine sif the robot is currently in Test mode as determined by the Driver Station. + * + * @return {@code True} if the robot is currently operating in Test mode. + */ + boolean isTest(); + + /** + * Determine if the robot is currently in Operator Control mode as determined by the Driver + * Station. + * + * @return {@code True} if the robot is currently operating in Operator Control mode. + */ + boolean isTeleop(); +} diff --git a/lib/src/main/java/com/team2813/lib2813/robot/SimplePeriodicRegistry.java b/lib/src/main/java/com/team2813/lib2813/robot/SimplePeriodicRegistry.java new file mode 100644 index 00000000..7e4f0b7c --- /dev/null +++ b/lib/src/main/java/com/team2813/lib2813/robot/SimplePeriodicRegistry.java @@ -0,0 +1,87 @@ +/* +Copyright 2026 Prospect Robotics SWENext Club + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package com.team2813.lib2813.robot; + +import edu.wpi.first.wpilibj.DriverStation; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +/** + * {@link PeriodicRegistry} implementation that gets the state from {@link DriverStation}. + * + *

Most code should not directly use this class. Subsystems can extend {@link + * com.team2813.lib2813.subsystems.ModularSubsystem} to get access to an instance of {@link + * PeriodicRegistry}. + * + *

Alternatively, the main robot code can construct this class, as long as it calls {@link + * #callPeriodicFunctions()} in {@code robotPeriodic()} and {@link + * #callSimulationPeriodicFunctions()} in {@code simulationPeriodic()}. + */ +public final class SimplePeriodicRegistry implements PeriodicRegistry { + private final List> periodicFunctions = new ArrayList<>(); + private final List> simulationPeriodicFunctions = new ArrayList<>(); + + @Override + public void addPeriodic(Consumer callback) { + periodicFunctions.add(callback); + } + + @Override + public void addSimulationPeriodic(Consumer callback) { + simulationPeriodicFunctions.add(callback); + } + + /** Calls all the callbacks added via {@link #addPeriodic(Consumer)}. */ + public void callPeriodicFunctions() { + RobotState robotState = SimpleRobotState.getInstance(); + periodicFunctions.forEach(fun -> fun.accept(robotState)); + } + + /** Calls all the callbacks added via {@link #addSimulationPeriodic(Consumer)}. */ + public void callSimulationPeriodicFunctions() { + RobotState robotState = SimpleRobotState.getInstance(); + simulationPeriodicFunctions.forEach(fun -> fun.accept(robotState)); + } + + private static class SimpleRobotState implements RobotState { + private static final SimpleRobotState INSTANCE = new SimpleRobotState(); + + static RobotState getInstance() { + return INSTANCE; + } + + @Override + public boolean isEnabled() { + return DriverStation.isEnabled(); + } + + @Override + public boolean isAutonomous() { + return DriverStation.isAutonomous(); + } + + @Override + public boolean isTest() { + return DriverStation.isTest(); + } + + @Override + public boolean isTeleop() { + return DriverStation.isTeleop(); + } + } +} diff --git a/lib/src/main/java/com/team2813/lib2813/subsystems/ModularSubsystem.java b/lib/src/main/java/com/team2813/lib2813/subsystems/ModularSubsystem.java new file mode 100644 index 00000000..f012f2c9 --- /dev/null +++ b/lib/src/main/java/com/team2813/lib2813/subsystems/ModularSubsystem.java @@ -0,0 +1,71 @@ +/* +Copyright 2026 Prospect Robotics SWENext Club + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package com.team2813.lib2813.subsystems; + +import com.team2813.lib2813.robot.PeriodicRegistry; +import com.team2813.lib2813.robot.SimplePeriodicRegistry; +import edu.wpi.first.wpilibj2.command.CommandScheduler; +import edu.wpi.first.wpilibj2.command.SubsystemBase; + +/** + * A base for subsystems that has APIs to support modular code. + * + *

Provides access to {@link PeriodicRegistry}, which can be passed to reusable components. + */ +public abstract class ModularSubsystem extends SubsystemBase { + private final SimplePeriodicRegistry periodicRegistry = new SimplePeriodicRegistry(); + + /** Constructor. Telemetry/log name defaults to the classname. */ + protected ModularSubsystem() { + super(); + } + + /** + * Constructor. + * + * @param name Name of the subsystem for telemetry and logging. + */ + protected ModularSubsystem(String name) { + super(name); + } + + /** + * Gets a periodic registry for registering functions to periodically be called by this subsystem. + */ + protected final PeriodicRegistry getPeriodicRegistry() { + return periodicRegistry; + } + + /** + * Called periodically by the {@link CommandScheduler}. + * + *

This is intentionally marked as final; subclasses should use {@link #getPeriodicRegistry()}. + */ + @Override + public final void periodic() { + periodicRegistry.callPeriodicFunctions(); + } + + /** + * Called periodically by the {@link CommandScheduler} when in simulation mode. + * + *

This is intentionally marked as final; subclasses should use {@link #getPeriodicRegistry()}. + */ + @Override + public final void simulationPeriodic() { + periodicRegistry.callSimulationPeriodicFunctions(); + } +}