[hal, wpilib] Add OpMode support (#7744)

User code:
- OpModeRobot used as the robot base class
- LinearOpMode and PeriodicOpMode are provided opmode base classes
- In Java, annotations can be used to automatically register opmode classes

Additional user code functionality:
- OpMode (string) is available in addition to the overall
auto/teleop/test robot mode
- OpMode does not indicate enable (enable/disable is still separate)
- The HAL API uses integer UIDs; these are exposed at the user API level
as well for faster checks
- User code creates opmodes on startup (these have name, category,
description, etc).

DS:
- DS will present opmode selection lists for auto and teleop for
match/practice. During a match, the DS will automatically activate the
selected opmode in the corresponding match period.
- For testing, an overall mode is selected (e.g. teleop/auto/test) and a
single opmode is selected

Future work:
- Command framework support/integration
- Python annotation support
- Unit tests (needs race-free DS sim updates)
- Porting of examples

Co-authored-by: Joseph Eng <91924258+KangarooKoala@users.noreply.github.com>
This commit is contained in:
Peter Johnson
2025-12-12 21:25:57 -07:00
committed by GitHub
parent 2a41b80e00
commit dacded37e5
163 changed files with 7454 additions and 2175 deletions

View File

@@ -13,6 +13,7 @@ import org.junit.jupiter.api.parallel.ResourceLock;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.wpilib.hardware.hal.HAL;
import org.wpilib.hardware.hal.RobotMode;
import org.wpilib.math.util.Units;
import org.wpilib.simulation.DriverStationSim;
import org.wpilib.simulation.EncoderSim;
@@ -75,7 +76,7 @@ class ArmSimulationTest {
assertEquals(setpoint, Preferences.getDouble(Constants.kArmPositionKey, Double.NaN));
// teleop init
{
DriverStationSim.setAutonomous(false);
DriverStationSim.setRobotMode(RobotMode.TELEOPERATED);
DriverStationSim.setEnabled(true);
DriverStationSim.notifyNewData();
@@ -135,7 +136,6 @@ class ArmSimulationTest {
{
// Disable
DriverStationSim.setAutonomous(false);
DriverStationSim.setEnabled(false);
DriverStationSim.notifyNewData();

View File

@@ -16,6 +16,7 @@ import org.junit.jupiter.params.provider.EnumSource;
import org.junit.jupiter.params.provider.ValueSource;
import org.wpilib.hardware.hal.AllianceStationID;
import org.wpilib.hardware.hal.HAL;
import org.wpilib.hardware.hal.RobotMode;
import org.wpilib.simulation.DIOSim;
import org.wpilib.simulation.DriverStationSim;
import org.wpilib.simulation.SimHooks;
@@ -88,7 +89,7 @@ class DigitalCommunicationTest {
@ValueSource(booleans = {true, false})
@ParameterizedTest(name = "autonomous[{index}]: {0}")
void autonomousTest(boolean autonomous) {
DriverStationSim.setAutonomous(autonomous);
DriverStationSim.setRobotMode(autonomous ? RobotMode.AUTONOMOUS : RobotMode.TELEOPERATED);
DriverStationSim.notifyNewData();
assertTrue(m_autonomousOutput.getInitialized());

View File

@@ -12,6 +12,7 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.parallel.ResourceLock;
import org.wpilib.hardware.hal.HAL;
import org.wpilib.hardware.hal.RobotMode;
import org.wpilib.simulation.DriverStationSim;
import org.wpilib.simulation.EncoderSim;
import org.wpilib.simulation.JoystickSim;
@@ -64,7 +65,7 @@ class ElevatorSimulationTest {
void teleopTest() {
// teleop init
{
DriverStationSim.setAutonomous(false);
DriverStationSim.setRobotMode(RobotMode.TELEOPERATED);
DriverStationSim.setEnabled(true);
DriverStationSim.notifyNewData();
@@ -124,7 +125,6 @@ class ElevatorSimulationTest {
{
// Disable
DriverStationSim.setAutonomous(false);
DriverStationSim.setEnabled(false);
DriverStationSim.notifyNewData();

View File

@@ -19,6 +19,7 @@ import org.junit.jupiter.params.provider.ValueSource;
import org.wpilib.driverstation.DriverStation;
import org.wpilib.hardware.hal.AllianceStationID;
import org.wpilib.hardware.hal.HAL;
import org.wpilib.hardware.hal.RobotMode;
import org.wpilib.simulation.CallbackStore;
import org.wpilib.simulation.DriverStationSim;
import org.wpilib.simulation.I2CSim;
@@ -100,7 +101,7 @@ class I2CCommunicationTest {
@ValueSource(booleans = {true, false})
@ParameterizedTest(name = "autonomous[{index}]: {0}")
void autonomousTest(boolean autonomous) {
DriverStationSim.setAutonomous(autonomous);
DriverStationSim.setRobotMode(autonomous ? RobotMode.AUTONOMOUS : RobotMode.TELEOPERATED);
DriverStationSim.notifyNewData();
assertTrue(m_i2c.getInitialized());

View File

@@ -13,6 +13,7 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.parallel.ResourceLock;
import org.wpilib.hardware.hal.HAL;
import org.wpilib.hardware.hal.HAL.SimPeriodicBeforeCallback;
import org.wpilib.hardware.hal.RobotMode;
import org.wpilib.math.system.plant.DCMotor;
import org.wpilib.math.util.Units;
import org.wpilib.simulation.AnalogInputSim;
@@ -100,7 +101,7 @@ class PotentiometerPIDTest {
void teleopTest() {
// teleop init
{
DriverStationSim.setAutonomous(false);
DriverStationSim.setRobotMode(RobotMode.TELEOPERATED);
DriverStationSim.setEnabled(true);
DriverStationSim.notifyNewData();