diff --git a/commandsv2/src/main/java/org/wpilib/command2/CommandScheduler.java b/commandsv2/src/main/java/org/wpilib/command2/CommandScheduler.java index 761f67e595..7736fe6dc1 100644 --- a/commandsv2/src/main/java/org/wpilib/command2/CommandScheduler.java +++ b/commandsv2/src/main/java/org/wpilib/command2/CommandScheduler.java @@ -23,7 +23,8 @@ import java.util.WeakHashMap; import java.util.function.BiConsumer; import java.util.function.Consumer; import org.wpilib.command2.Command.InterruptionBehavior; -import org.wpilib.driverstation.DriverStation; +import org.wpilib.driverstation.DriverStationErrors; +import org.wpilib.driverstation.RobotState; import org.wpilib.event.EventLoop; import org.wpilib.framework.RobotBase; import org.wpilib.framework.TimedRobot; @@ -175,7 +176,7 @@ public final class CommandScheduler implements Sendable, AutoCloseable { */ private void schedule(Command command) { if (command == null) { - DriverStation.reportWarning("Tried to schedule a null command", true); + DriverStationErrors.reportWarning("Tried to schedule a null command", true); return; } if (m_inRunLoop) { @@ -189,7 +190,7 @@ public final class CommandScheduler implements Sendable, AutoCloseable { // run when disabled, or the command is already scheduled. if (m_disabled || isScheduled(command) - || DriverStation.isDisabled() && !command.runsWhenDisabled()) { + || RobotState.isDisabled() && !command.runsWhenDisabled()) { return; } @@ -269,7 +270,7 @@ public final class CommandScheduler implements Sendable, AutoCloseable { m_watchdog.addEpoch("buttons.run()"); m_inRunLoop = true; - boolean isDisabled = DriverStation.isDisabled(); + boolean isDisabled = RobotState.isDisabled(); // Run scheduled commands, remove finished commands. for (Iterator iterator = m_scheduledCommands.iterator(); iterator.hasNext(); ) { Command command = iterator.next(); @@ -337,11 +338,12 @@ public final class CommandScheduler implements Sendable, AutoCloseable { public void registerSubsystem(Subsystem... subsystems) { for (Subsystem subsystem : subsystems) { if (subsystem == null) { - DriverStation.reportWarning("Tried to register a null subsystem", true); + DriverStationErrors.reportWarning("Tried to register a null subsystem", true); continue; } if (m_subsystems.containsKey(subsystem)) { - DriverStation.reportWarning("Tried to register an already-registered subsystem", true); + DriverStationErrors.reportWarning( + "Tried to register an already-registered subsystem", true); continue; } m_subsystems.put(subsystem, null); @@ -379,11 +381,12 @@ public final class CommandScheduler implements Sendable, AutoCloseable { */ public void setDefaultCommand(Subsystem subsystem, Command defaultCommand) { if (subsystem == null) { - DriverStation.reportWarning("Tried to set a default command for a null subsystem", true); + DriverStationErrors.reportWarning( + "Tried to set a default command for a null subsystem", true); return; } if (defaultCommand == null) { - DriverStation.reportWarning("Tried to set a null default command", true); + DriverStationErrors.reportWarning("Tried to set a null default command", true); return; } @@ -394,7 +397,7 @@ public final class CommandScheduler implements Sendable, AutoCloseable { } if (defaultCommand.getInterruptionBehavior() == InterruptionBehavior.kCancelIncoming) { - DriverStation.reportWarning( + DriverStationErrors.reportWarning( "Registering a non-interruptible default command!\n" + "This will likely prevent any other commands from requiring this subsystem.", true); @@ -413,7 +416,8 @@ public final class CommandScheduler implements Sendable, AutoCloseable { */ public void removeDefaultCommand(Subsystem subsystem) { if (subsystem == null) { - DriverStation.reportWarning("Tried to remove a default command for a null subsystem", true); + DriverStationErrors.reportWarning( + "Tried to remove a default command for a null subsystem", true); return; } @@ -458,7 +462,7 @@ public final class CommandScheduler implements Sendable, AutoCloseable { */ private void cancel(Command command, Optional interruptor) { if (command == null) { - DriverStation.reportWarning("Tried to cancel a null command", true); + DriverStationErrors.reportWarning("Tried to cancel a null command", true); return; } if (m_endingCommands.contains(command)) { diff --git a/commandsv2/src/main/java/org/wpilib/command2/WaitUntilCommand.java b/commandsv2/src/main/java/org/wpilib/command2/WaitUntilCommand.java index 6e8606df30..9c17b88ddf 100644 --- a/commandsv2/src/main/java/org/wpilib/command2/WaitUntilCommand.java +++ b/commandsv2/src/main/java/org/wpilib/command2/WaitUntilCommand.java @@ -39,7 +39,7 @@ public class WaitUntilCommand extends Command { * wait. * * @param time the match time after which to end, in seconds - * @see org.wpilib.driverstation.DriverStation#getMatchTime() + * @see org.wpilib.driverstation.MatchState#getMatchTime() */ public WaitUntilCommand(double time) { this(() -> Timer.getMatchTime() < time); diff --git a/commandsv2/src/main/java/org/wpilib/command2/button/CommandGenericHID.java b/commandsv2/src/main/java/org/wpilib/command2/button/CommandGenericHID.java index 6d64ca990a..10dd5ba5c9 100644 --- a/commandsv2/src/main/java/org/wpilib/command2/button/CommandGenericHID.java +++ b/commandsv2/src/main/java/org/wpilib/command2/button/CommandGenericHID.java @@ -7,8 +7,8 @@ package org.wpilib.command2.button; import java.util.HashMap; import java.util.Map; import org.wpilib.command2.CommandScheduler; -import org.wpilib.driverstation.DriverStation.POVDirection; import org.wpilib.driverstation.GenericHID; +import org.wpilib.driverstation.POVDirection; import org.wpilib.event.EventLoop; import org.wpilib.math.util.Pair; diff --git a/commandsv2/src/main/java/org/wpilib/command2/button/POVButton.java b/commandsv2/src/main/java/org/wpilib/command2/button/POVButton.java index 5727710406..07415110aa 100644 --- a/commandsv2/src/main/java/org/wpilib/command2/button/POVButton.java +++ b/commandsv2/src/main/java/org/wpilib/command2/button/POVButton.java @@ -6,8 +6,8 @@ package org.wpilib.command2.button; import static org.wpilib.util.ErrorMessages.requireNonNullParam; -import org.wpilib.driverstation.DriverStation.POVDirection; import org.wpilib.driverstation.GenericHID; +import org.wpilib.driverstation.POVDirection; /** * A {@link Trigger} that gets its state from a POV on a {@link GenericHID}. diff --git a/commandsv2/src/main/java/org/wpilib/command2/button/RobotModeTriggers.java b/commandsv2/src/main/java/org/wpilib/command2/button/RobotModeTriggers.java index 8edcea3208..f21adf62b1 100644 --- a/commandsv2/src/main/java/org/wpilib/command2/button/RobotModeTriggers.java +++ b/commandsv2/src/main/java/org/wpilib/command2/button/RobotModeTriggers.java @@ -4,7 +4,7 @@ package org.wpilib.command2.button; -import org.wpilib.driverstation.DriverStation; +import org.wpilib.driverstation.RobotState; /** * A class containing static {@link Trigger} factories for running callbacks when the robot mode @@ -20,7 +20,7 @@ public final class RobotModeTriggers { * @return A trigger that is true when the robot is enabled in autonomous mode. */ public static Trigger autonomous() { - return new Trigger(DriverStation::isAutonomousEnabled); + return new Trigger(RobotState::isAutonomousEnabled); } /** @@ -29,7 +29,7 @@ public final class RobotModeTriggers { * @return A trigger that is true when the robot is enabled in teleop mode. */ public static Trigger teleop() { - return new Trigger(DriverStation::isTeleopEnabled); + return new Trigger(RobotState::isTeleopEnabled); } /** @@ -38,7 +38,7 @@ public final class RobotModeTriggers { * @return A trigger that is true when the robot is disabled. */ public static Trigger disabled() { - return new Trigger(DriverStation::isDisabled); + return new Trigger(RobotState::isDisabled); } /** @@ -47,6 +47,6 @@ public final class RobotModeTriggers { * @return A trigger that is true when the robot is enabled in test mode. */ public static Trigger test() { - return new Trigger(DriverStation::isTestEnabled); + return new Trigger(RobotState::isTestEnabled); } } diff --git a/commandsv2/src/main/native/cpp/frc2/command/CommandScheduler.cpp b/commandsv2/src/main/native/cpp/frc2/command/CommandScheduler.cpp index a43adf2fb2..f4b622c9ea 100644 --- a/commandsv2/src/main/native/cpp/frc2/command/CommandScheduler.cpp +++ b/commandsv2/src/main/native/cpp/frc2/command/CommandScheduler.cpp @@ -12,7 +12,7 @@ #include "wpi/commands2/CommandPtr.hpp" #include "wpi/commands2/Subsystem.hpp" -#include "wpi/driverstation/DriverStation.hpp" +#include "wpi/driverstation/RobotState.hpp" #include "wpi/framework/RobotBase.hpp" #include "wpi/framework/TimedRobot.hpp" #include "wpi/hal/UsageReporting.hpp" @@ -99,7 +99,7 @@ void CommandScheduler::Schedule(Command* command) { RequireUngrouped(command); if (m_impl->disabled || m_impl->scheduledCommands.contains(command) || - (wpi::DriverStation::IsDisabled() && !command->RunsWhenDisabled())) { + (wpi::RobotState::IsDisabled() && !command->RunsWhenDisabled())) { return; } @@ -181,7 +181,7 @@ void CommandScheduler::Run() { loopCache->Poll(); m_watchdog.AddEpoch("buttons.Run()"); - bool isDisabled = wpi::DriverStation::IsDisabled(); + bool isDisabled = wpi::RobotState::IsDisabled(); // create a new set to avoid iterator invalidation. for (Command* command : wpi::util::SmallSet(m_impl->scheduledCommands)) { if (!IsScheduled(command)) { diff --git a/commandsv2/src/main/native/cpp/frc2/command/button/CommandGenericHID.cpp b/commandsv2/src/main/native/cpp/frc2/command/button/CommandGenericHID.cpp index e8808a9f5c..14c3721256 100644 --- a/commandsv2/src/main/native/cpp/frc2/command/button/CommandGenericHID.cpp +++ b/commandsv2/src/main/native/cpp/frc2/command/button/CommandGenericHID.cpp @@ -16,51 +16,51 @@ Trigger CommandGenericHID::Button(int button, wpi::EventLoop* loop) const { return Trigger(loop, [this, button] { return m_hid.GetRawButton(button); }); } -Trigger CommandGenericHID::POV(wpi::DriverStation::POVDirection angle, +Trigger CommandGenericHID::POV(wpi::POVDirection angle, wpi::EventLoop* loop) const { return POV(0, angle, loop); } -Trigger CommandGenericHID::POV(int pov, wpi::DriverStation::POVDirection angle, +Trigger CommandGenericHID::POV(int pov, wpi::POVDirection angle, wpi::EventLoop* loop) const { return Trigger(loop, [this, pov, angle] { return m_hid.GetPOV(pov) == angle; }); } Trigger CommandGenericHID::POVUp(wpi::EventLoop* loop) const { - return POV(wpi::DriverStation::POVDirection::UP, loop); + return POV(wpi::POVDirection::UP, loop); } Trigger CommandGenericHID::POVUpRight(wpi::EventLoop* loop) const { - return POV(wpi::DriverStation::POVDirection::UP_RIGHT, loop); + return POV(wpi::POVDirection::UP_RIGHT, loop); } Trigger CommandGenericHID::POVRight(wpi::EventLoop* loop) const { - return POV(wpi::DriverStation::POVDirection::RIGHT, loop); + return POV(wpi::POVDirection::RIGHT, loop); } Trigger CommandGenericHID::POVDownRight(wpi::EventLoop* loop) const { - return POV(wpi::DriverStation::POVDirection::DOWN_RIGHT, loop); + return POV(wpi::POVDirection::DOWN_RIGHT, loop); } Trigger CommandGenericHID::POVDown(wpi::EventLoop* loop) const { - return POV(wpi::DriverStation::POVDirection::DOWN, loop); + return POV(wpi::POVDirection::DOWN, loop); } Trigger CommandGenericHID::POVDownLeft(wpi::EventLoop* loop) const { - return POV(wpi::DriverStation::POVDirection::DOWN_LEFT, loop); + return POV(wpi::POVDirection::DOWN_LEFT, loop); } Trigger CommandGenericHID::POVLeft(wpi::EventLoop* loop) const { - return POV(wpi::DriverStation::POVDirection::LEFT, loop); + return POV(wpi::POVDirection::LEFT, loop); } Trigger CommandGenericHID::POVUpLeft(wpi::EventLoop* loop) const { - return POV(wpi::DriverStation::POVDirection::UP_LEFT, loop); + return POV(wpi::POVDirection::UP_LEFT, loop); } Trigger CommandGenericHID::POVCenter(wpi::EventLoop* loop) const { - return POV(wpi::DriverStation::POVDirection::CENTER, loop); + return POV(wpi::POVDirection::CENTER, loop); } Trigger CommandGenericHID::AxisLessThan(int axis, double threshold, diff --git a/commandsv2/src/main/native/cpp/frc2/command/button/RobotModeTriggers.cpp b/commandsv2/src/main/native/cpp/frc2/command/button/RobotModeTriggers.cpp index 486b4705d8..ff58cecda2 100644 --- a/commandsv2/src/main/native/cpp/frc2/command/button/RobotModeTriggers.cpp +++ b/commandsv2/src/main/native/cpp/frc2/command/button/RobotModeTriggers.cpp @@ -4,22 +4,22 @@ #include "wpi/commands2/button/RobotModeTriggers.hpp" -#include "wpi/driverstation/DriverStation.hpp" +#include "wpi/driverstation/RobotState.hpp" using namespace wpi::cmd; Trigger RobotModeTriggers::Autonomous() { - return Trigger{&wpi::DriverStation::IsAutonomousEnabled}; + return Trigger{&wpi::RobotState::IsAutonomousEnabled}; } Trigger RobotModeTriggers::Teleop() { - return Trigger{&wpi::DriverStation::IsTeleopEnabled}; + return Trigger{&wpi::RobotState::IsTeleopEnabled}; } Trigger RobotModeTriggers::Disabled() { - return Trigger{&wpi::DriverStation::IsDisabled}; + return Trigger{&wpi::RobotState::IsDisabled}; } Trigger RobotModeTriggers::Test() { - return Trigger{&wpi::DriverStation::IsTestEnabled}; + return Trigger{&wpi::RobotState::IsTestEnabled}; } diff --git a/commandsv2/src/main/native/include/wpi/commands2/button/CommandGenericHID.hpp b/commandsv2/src/main/native/include/wpi/commands2/button/CommandGenericHID.hpp index 90b192b6d4..4291e8a1a1 100644 --- a/commandsv2/src/main/native/include/wpi/commands2/button/CommandGenericHID.hpp +++ b/commandsv2/src/main/native/include/wpi/commands2/button/CommandGenericHID.hpp @@ -6,8 +6,9 @@ #include "wpi/commands2/CommandScheduler.hpp" #include "wpi/commands2/button/Trigger.hpp" -#include "wpi/driverstation/DriverStation.hpp" #include "wpi/driverstation/GenericHID.hpp" +#include "wpi/driverstation/POVDirection.hpp" +#include "wpi/driverstation/internal/DriverStationBackend.hpp" namespace wpi::cmd { @@ -56,7 +57,7 @@ class CommandGenericHID { * @param angle POV angle. * @return a Trigger instance based around this angle of a POV on the HID. */ - Trigger POV(wpi::DriverStation::POVDirection angle, + Trigger POV(wpi::POVDirection angle, wpi::EventLoop* loop = CommandScheduler::GetInstance().GetDefaultButtonLoop()) const; @@ -70,7 +71,7 @@ class CommandGenericHID { * @param angle POV angle. * @return a Trigger instance based around this angle of a POV on the HID. */ - Trigger POV(int pov, wpi::DriverStation::POVDirection angle, + Trigger POV(int pov, wpi::POVDirection angle, wpi::EventLoop* loop = CommandScheduler::GetInstance().GetDefaultButtonLoop()) const; diff --git a/commandsv2/src/main/native/include/wpi/commands2/button/POVButton.hpp b/commandsv2/src/main/native/include/wpi/commands2/button/POVButton.hpp index e2b58fa333..78dd2115dc 100644 --- a/commandsv2/src/main/native/include/wpi/commands2/button/POVButton.hpp +++ b/commandsv2/src/main/native/include/wpi/commands2/button/POVButton.hpp @@ -5,8 +5,8 @@ #pragma once #include "wpi/commands2/button/Trigger.hpp" -#include "wpi/driverstation/DriverStation.hpp" #include "wpi/driverstation/GenericHID.hpp" +#include "wpi/driverstation/POVDirection.hpp" namespace wpi::cmd { /** @@ -26,7 +26,7 @@ class POVButton : public Trigger { * @param angle The angle of the POV corresponding to a button press. * @param povNumber The number of the POV on the joystick. */ - POVButton(wpi::GenericHID* joystick, wpi::DriverStation::POVDirection angle, + POVButton(wpi::GenericHID* joystick, wpi::POVDirection angle, int povNumber = 0) : Trigger([joystick, angle, povNumber] { return joystick->GetPOV(povNumber) == angle; diff --git a/commandsv2/src/main/python/commands2/commandscheduler.py b/commandsv2/src/main/python/commands2/commandscheduler.py index b99eebbdbe..e03c1161d8 100644 --- a/commandsv2/src/main/python/commands2/commandscheduler.py +++ b/commandsv2/src/main/python/commands2/commandscheduler.py @@ -9,7 +9,7 @@ from typing import Any, Callable, Dict, Iterable, List, Optional, Set, Union import hal from typing_extensions import Self from wpilib import ( - DriverStation, + RobotState, EventLoop, RobotBase, TimedRobot, @@ -192,7 +192,7 @@ class CommandScheduler(Sendable): if self.isScheduled(command): return - if DriverStation.isDisabled() and not command.runsWhenDisabled(): + if RobotState.isDisabled() and not command.runsWhenDisabled(): return requirements = command.getRequirements() @@ -250,7 +250,7 @@ class CommandScheduler(Sendable): self._watchdog.addEpoch("buttons.run()") self._inRunLoop = True - isDisabled = DriverStation.isDisabled() + isDisabled = RobotState.isDisabled() # Run scheduled commands, remove finished commands. for command in self._scheduledCommands.copy(): diff --git a/commandsv2/src/test/java/org/wpilib/command2/CommandTestBase.java b/commandsv2/src/test/java/org/wpilib/command2/CommandTestBase.java index 6b59ca6b09..055feb34f4 100644 --- a/commandsv2/src/test/java/org/wpilib/command2/CommandTestBase.java +++ b/commandsv2/src/test/java/org/wpilib/command2/CommandTestBase.java @@ -10,7 +10,7 @@ import static org.mockito.Mockito.when; import java.util.Set; import org.junit.jupiter.api.BeforeEach; import org.wpilib.command2.Command.InterruptionBehavior; -import org.wpilib.driverstation.DriverStation; +import org.wpilib.driverstation.RobotState; import org.wpilib.simulation.DriverStationSim; /** Basic setup for all {@link Command tests}. */ @@ -33,7 +33,7 @@ public class CommandTestBase { DriverStationSim.setEnabled(enabled); DriverStationSim.notifyNewData(); - while (DriverStation.isEnabled() != enabled) { + while (RobotState.isEnabled() != enabled) { try { Thread.sleep(1); } catch (InterruptedException exception) { diff --git a/commandsv2/src/test/native/cpp/wpi/command/POVButtonTest.cpp b/commandsv2/src/test/native/cpp/wpi/command/POVButtonTest.cpp index d21c01c01f..8f5f8be5e9 100644 --- a/commandsv2/src/test/native/cpp/wpi/command/POVButtonTest.cpp +++ b/commandsv2/src/test/native/cpp/wpi/command/POVButtonTest.cpp @@ -10,8 +10,8 @@ #include "wpi/commands2/CommandScheduler.hpp" #include "wpi/commands2/RunCommand.hpp" #include "wpi/commands2/WaitUntilCommand.hpp" -#include "wpi/driverstation/DriverStation.hpp" #include "wpi/driverstation/Joystick.hpp" +#include "wpi/driverstation/internal/DriverStationBackend.hpp" #include "wpi/simulation/JoystickSim.hpp" using namespace wpi::cmd; @@ -19,7 +19,7 @@ class POVButtonTest : public CommandTestBase {}; TEST_F(POVButtonTest, SetPOV) { wpi::sim::JoystickSim joysim(1); - joysim.SetPOV(wpi::DriverStation::POVDirection::UP); + joysim.SetPOV(wpi::POVDirection::UP); joysim.NotifyNewData(); auto& scheduler = CommandScheduler::GetInstance(); @@ -28,11 +28,11 @@ TEST_F(POVButtonTest, SetPOV) { WaitUntilCommand command([&finished] { return finished; }); wpi::Joystick joy(1); - POVButton(&joy, wpi::DriverStation::POVDirection::RIGHT).OnTrue(&command); + POVButton(&joy, wpi::POVDirection::RIGHT).OnTrue(&command); scheduler.Run(); EXPECT_FALSE(scheduler.IsScheduled(&command)); - joysim.SetPOV(wpi::DriverStation::POVDirection::RIGHT); + joysim.SetPOV(wpi::POVDirection::RIGHT); joysim.NotifyNewData(); scheduler.Run(); diff --git a/commandsv2/src/test/native/cpp/wpi/command/button/RobotModeTriggersTest.cpp b/commandsv2/src/test/native/cpp/wpi/command/button/RobotModeTriggersTest.cpp index dacf5cd74e..f97f0e8090 100644 --- a/commandsv2/src/test/native/cpp/wpi/command/button/RobotModeTriggersTest.cpp +++ b/commandsv2/src/test/native/cpp/wpi/command/button/RobotModeTriggersTest.cpp @@ -6,7 +6,7 @@ #include "../CommandTestBase.hpp" #include "wpi/commands2/button/Trigger.hpp" -#include "wpi/driverstation/DriverStation.hpp" +#include "wpi/driverstation/internal/DriverStationBackend.hpp" #include "wpi/hal/DriverStationTypes.h" #include "wpi/simulation/DriverStationSim.hpp" diff --git a/commandsv3/src/main/java/org/wpilib/command3/OpModeFetcher.java b/commandsv3/src/main/java/org/wpilib/command3/OpModeFetcher.java index 997852827b..6dd186ae3d 100644 --- a/commandsv3/src/main/java/org/wpilib/command3/OpModeFetcher.java +++ b/commandsv3/src/main/java/org/wpilib/command3/OpModeFetcher.java @@ -6,7 +6,7 @@ package org.wpilib.command3; import static org.wpilib.util.ErrorMessages.requireNonNullParam; -import org.wpilib.driverstation.DriverStation; +import org.wpilib.driverstation.RobotState; /** * Helper class for fetching information about the current opmode. This is a package-private class @@ -52,12 +52,12 @@ abstract class OpModeFetcher { static final class DriverStationOpModeFetcher extends OpModeFetcher { @Override public long getOpModeId() { - return DriverStation.getOpModeId(); + return RobotState.getOpModeId(); } @Override public String getOpModeName() { - return DriverStation.getOpMode(); + return RobotState.getOpMode(); } } } diff --git a/commandsv3/src/main/java/org/wpilib/command3/button/CommandGenericHID.java b/commandsv3/src/main/java/org/wpilib/command3/button/CommandGenericHID.java index bc6596d3c7..2051d6ccd9 100644 --- a/commandsv3/src/main/java/org/wpilib/command3/button/CommandGenericHID.java +++ b/commandsv3/src/main/java/org/wpilib/command3/button/CommandGenericHID.java @@ -8,8 +8,8 @@ import java.util.HashMap; import java.util.Map; import org.wpilib.command3.Scheduler; import org.wpilib.command3.Trigger; -import org.wpilib.driverstation.DriverStation.POVDirection; import org.wpilib.driverstation.GenericHID; +import org.wpilib.driverstation.POVDirection; import org.wpilib.event.EventLoop; import org.wpilib.math.util.Pair; diff --git a/commandsv3/src/main/java/org/wpilib/command3/button/POVButton.java b/commandsv3/src/main/java/org/wpilib/command3/button/POVButton.java index 724e8695cb..565ee595e0 100644 --- a/commandsv3/src/main/java/org/wpilib/command3/button/POVButton.java +++ b/commandsv3/src/main/java/org/wpilib/command3/button/POVButton.java @@ -7,8 +7,8 @@ package org.wpilib.command3.button; import static org.wpilib.util.ErrorMessages.requireNonNullParam; import org.wpilib.command3.Trigger; -import org.wpilib.driverstation.DriverStation.POVDirection; import org.wpilib.driverstation.GenericHID; +import org.wpilib.driverstation.POVDirection; /** A {@link Trigger} that gets its state from a POV on a {@link GenericHID}. */ public class POVButton extends Trigger { diff --git a/commandsv3/src/main/java/org/wpilib/command3/button/RobotModeTriggers.java b/commandsv3/src/main/java/org/wpilib/command3/button/RobotModeTriggers.java index e41eec9906..cbb513161e 100644 --- a/commandsv3/src/main/java/org/wpilib/command3/button/RobotModeTriggers.java +++ b/commandsv3/src/main/java/org/wpilib/command3/button/RobotModeTriggers.java @@ -5,7 +5,7 @@ package org.wpilib.command3.button; import org.wpilib.command3.Trigger; -import org.wpilib.driverstation.DriverStation; +import org.wpilib.driverstation.RobotState; /** * A class containing static {@link Trigger} factories for running callbacks when the robot mode @@ -21,7 +21,7 @@ public final class RobotModeTriggers { * @return A trigger that is true when the robot is enabled in autonomous mode. */ public static Trigger autonomous() { - return new Trigger(DriverStation::isAutonomousEnabled); + return new Trigger(RobotState::isAutonomousEnabled); } /** @@ -30,7 +30,7 @@ public final class RobotModeTriggers { * @return A trigger that is true when the robot is enabled in teleop mode. */ public static Trigger teleop() { - return new Trigger(DriverStation::isTeleopEnabled); + return new Trigger(RobotState::isTeleopEnabled); } /** @@ -39,7 +39,7 @@ public final class RobotModeTriggers { * @return A trigger that is true when the robot is disabled. */ public static Trigger disabled() { - return new Trigger(DriverStation::isDisabled); + return new Trigger(RobotState::isDisabled); } /** @@ -48,6 +48,6 @@ public final class RobotModeTriggers { * @return A trigger that is true when the robot is enabled in test mode. */ public static Trigger test() { - return new Trigger(DriverStation::isTestEnabled); + return new Trigger(RobotState::isTestEnabled); } } diff --git a/robotpyExamples/DigitalCommunication/robot.py b/robotpyExamples/DigitalCommunication/robot.py index ccc1ff5ae0..de6662ba0b 100755 --- a/robotpyExamples/DigitalCommunication/robot.py +++ b/robotpyExamples/DigitalCommunication/robot.py @@ -31,19 +31,19 @@ class MyRobot(wpilib.TimedRobot): def robotPeriodic(self): setAlliance = False - alliance = wpilib.DriverStation.getAlliance() + alliance = wpilib.MatchState.getAlliance() if alliance: - setAlliance = alliance == wpilib.DriverStation.Alliance.RED + setAlliance = alliance == wpilib.Alliance.RED # pull alliance port high if on red alliance, pull low if on blue alliance self.allianceOutput.set(setAlliance) # pull enabled port high if enabled, low if disabled - self.enabledOutput.set(wpilib.DriverStation.isEnabled()) + self.enabledOutput.set(wpilib.RobotState.isEnabled()) # pull auto port high if in autonomous, low if in teleop (or disabled) - self.autonomousOutput.set(wpilib.DriverStation.isAutonomous()) + self.autonomousOutput.set(wpilib.RobotState.isAutonomous()) # pull alert port high if match time remaining is between 30 and 25 seconds - matchTime = wpilib.DriverStation.getMatchTime() + matchTime = wpilib.MatchState.getMatchTime() self.alertOutput.set(30 >= matchTime >= 25) diff --git a/robotpyExamples/I2CCommunication/robot.py b/robotpyExamples/I2CCommunication/robot.py index 11406dbd28..ed902c5157 100755 --- a/robotpyExamples/I2CCommunication/robot.py +++ b/robotpyExamples/I2CCommunication/robot.py @@ -41,15 +41,15 @@ class MyRobot(wpilib.TimedRobot): # For example, "RET043" would indicate that the robot is on the red # alliance, enabled in teleop mode, with 43 seconds left in the match. allianceString = "U" - alliance = wpilib.DriverStation.getAlliance() + alliance = wpilib.MatchState.getAlliance() if alliance is not None: allianceString = ( - "R" if alliance == wpilib.DriverStation.Alliance.RED else "B" + "R" if alliance == wpilib.Alliance.RED else "B" ) - enabledString = "E" if wpilib.DriverStation.isEnabled() else "D" - autoString = "A" if wpilib.DriverStation.isAutonomous() else "T" - matchTime = wpilib.DriverStation.getMatchTime() + enabledString = "E" if wpilib.RobotState.isEnabled() else "D" + autoString = "A" if wpilib.RobotState.isAutonomous() else "T" + matchTime = wpilib.MatchState.getMatchTime() stateMessage = f"{allianceString}{enabledString}{autoString}{matchTime:03f}" diff --git a/romiVendordep/src/main/java/org/wpilib/romi/OnBoardIO.java b/romiVendordep/src/main/java/org/wpilib/romi/OnBoardIO.java index 7158719b97..8dc3fccc82 100644 --- a/romiVendordep/src/main/java/org/wpilib/romi/OnBoardIO.java +++ b/romiVendordep/src/main/java/org/wpilib/romi/OnBoardIO.java @@ -4,7 +4,7 @@ package org.wpilib.romi; -import org.wpilib.driverstation.DriverStation; +import org.wpilib.driverstation.DriverStationErrors; import org.wpilib.hardware.discrete.DigitalInput; import org.wpilib.hardware.discrete.DigitalOutput; import org.wpilib.system.Timer; @@ -84,7 +84,7 @@ public class OnBoardIO { double currentTime = Timer.getTimestamp(); if (currentTime > m_nextMessageTime) { - DriverStation.reportError("Button B was not configured", true); + DriverStationErrors.reportError("Button B was not configured", true); m_nextMessageTime = currentTime + MESSAGE_INTERVAL; } return false; @@ -102,7 +102,7 @@ public class OnBoardIO { double currentTime = Timer.getTimestamp(); if (currentTime > m_nextMessageTime) { - DriverStation.reportError("Button C was not configured", true); + DriverStationErrors.reportError("Button C was not configured", true); m_nextMessageTime = currentTime + MESSAGE_INTERVAL; } return false; @@ -119,7 +119,7 @@ public class OnBoardIO { } else { double currentTime = Timer.getTimestamp(); if (currentTime > m_nextMessageTime) { - DriverStation.reportError("Green LED was not configured", true); + DriverStationErrors.reportError("Green LED was not configured", true); m_nextMessageTime = currentTime + MESSAGE_INTERVAL; } } @@ -136,7 +136,7 @@ public class OnBoardIO { } else { double currentTime = Timer.getTimestamp(); if (currentTime > m_nextMessageTime) { - DriverStation.reportError("Red LED was not configured", true); + DriverStationErrors.reportError("Red LED was not configured", true); m_nextMessageTime = currentTime + MESSAGE_INTERVAL; } } diff --git a/styleguide/spotbugs-exclude.xml b/styleguide/spotbugs-exclude.xml index c32841935f..7f8c641dcd 100644 --- a/styleguide/spotbugs-exclude.xml +++ b/styleguide/spotbugs-exclude.xml @@ -7,7 +7,7 @@ - + diff --git a/wpilibc/robotpy_pybind_build_info.bzl b/wpilibc/robotpy_pybind_build_info.bzl index 42987ff146..3c4f7f512c 100644 --- a/wpilibc/robotpy_pybind_build_info.bzl +++ b/wpilibc/robotpy_pybind_build_info.bzl @@ -96,6 +96,24 @@ def wpilib_extension(srcs = [], header_to_dat_deps = [], extra_hdrs = [], includ ("wpi::RobotDriveBase", "wpi__RobotDriveBase.hpp"), ], ), + struct( + class_name = "DriverStationBackend", + yml_file = "semiwrap/DriverStationBackend.yml", + header_root = "$(execpath :robotpy-native-wpilib.copy_headers)", + header_file = "$(execpath :robotpy-native-wpilib.copy_headers)/wpi/driverstation/internal/DriverStationBackend.hpp", + tmpl_class_names = [], + trampolines = [ + ("wpi::internal::DriverStationBackend", "wpi__internal__DriverStationBackend.hpp"), + ], + ), + struct( + class_name = "Alliance", + yml_file = "semiwrap/Alliance.yml", + header_root = "$(execpath :robotpy-native-wpilib.copy_headers)", + header_file = "$(execpath :robotpy-native-wpilib.copy_headers)/wpi/driverstation/Alliance.hpp", + tmpl_class_names = [], + trampolines = [], + ), struct( class_name = "Alert", yml_file = "semiwrap/Alert.yml", @@ -114,7 +132,52 @@ def wpilib_extension(srcs = [], header_to_dat_deps = [], extra_hdrs = [], includ tmpl_class_names = [], trampolines = [ ("wpi::DriverStation", "wpi__DriverStation.hpp"), - ("wpi::DriverStation::TouchpadFinger", "wpi__DriverStation__TouchpadFinger.hpp"), + ], + ), + struct( + class_name = "MatchState", + yml_file = "semiwrap/MatchState.yml", + header_root = "$(execpath :robotpy-native-wpilib.copy_headers)", + header_file = "$(execpath :robotpy-native-wpilib.copy_headers)/wpi/driverstation/MatchState.hpp", + tmpl_class_names = [], + trampolines = [ + ("wpi::MatchState", "wpi__MatchState.hpp"), + ], + ), + struct( + class_name = "MatchType", + yml_file = "semiwrap/MatchType.yml", + header_root = "$(execpath :robotpy-native-wpilib.copy_headers)", + header_file = "$(execpath :robotpy-native-wpilib.copy_headers)/wpi/driverstation/MatchType.hpp", + tmpl_class_names = [], + trampolines = [], + ), + struct( + class_name = "POVDirection", + yml_file = "semiwrap/POVDirection.yml", + header_root = "$(execpath :robotpy-native-wpilib.copy_headers)", + header_file = "$(execpath :robotpy-native-wpilib.copy_headers)/wpi/driverstation/POVDirection.hpp", + tmpl_class_names = [], + trampolines = [], + ), + struct( + class_name = "RobotState", + yml_file = "semiwrap/RobotState.yml", + header_root = "$(execpath :robotpy-native-wpilib.copy_headers)", + header_file = "$(execpath :robotpy-native-wpilib.copy_headers)/wpi/driverstation/RobotState.hpp", + tmpl_class_names = [], + trampolines = [ + ("wpi::RobotState", "wpi__RobotState.hpp"), + ], + ), + struct( + class_name = "TouchpadFinger", + yml_file = "semiwrap/TouchpadFinger.yml", + header_root = "$(execpath :robotpy-native-wpilib.copy_headers)", + header_file = "$(execpath :robotpy-native-wpilib.copy_headers)/wpi/driverstation/TouchpadFinger.hpp", + tmpl_class_names = [], + trampolines = [ + ("wpi::TouchpadFinger", "wpi__TouchpadFinger.hpp"), ], ), struct( diff --git a/wpilibc/src/main/native/cpp/driverstation/Gamepad.cpp b/wpilibc/src/main/native/cpp/driverstation/Gamepad.cpp index c1a7665a22..1653f2e71a 100644 --- a/wpilibc/src/main/native/cpp/driverstation/Gamepad.cpp +++ b/wpilibc/src/main/native/cpp/driverstation/Gamepad.cpp @@ -505,14 +505,14 @@ BooleanEvent Gamepad::AxisGreaterThan(Axis axis, double threshold, } double Gamepad::GetAxisForSendable(Axis axis) const { - return DriverStation::GetStickAxisIfAvailable(GetPort(), - static_cast(axis)) + return wpi::internal::DriverStationBackend::GetStickAxisIfAvailable( + GetPort(), static_cast(axis)) .value_or(0.0); } bool Gamepad::GetButtonForSendable(Button button) const { - return DriverStation::GetStickButtonIfAvailable(GetPort(), - static_cast(button)) + return wpi::internal::DriverStationBackend::GetStickButtonIfAvailable( + GetPort(), static_cast(button)) .value_or(false); } diff --git a/wpilibc/src/main/native/cpp/driverstation/GenericHID.cpp b/wpilibc/src/main/native/cpp/driverstation/GenericHID.cpp index a7cab0eead..3de53f54bb 100644 --- a/wpilibc/src/main/native/cpp/driverstation/GenericHID.cpp +++ b/wpilibc/src/main/native/cpp/driverstation/GenericHID.cpp @@ -6,7 +6,7 @@ #include -#include "wpi/driverstation/DriverStation.hpp" +#include "wpi/driverstation/internal/DriverStationBackend.hpp" #include "wpi/event/BooleanEvent.hpp" #include "wpi/hal/DriverStation.h" #include "wpi/system/Errors.hpp" @@ -14,7 +14,7 @@ using namespace wpi; GenericHID::GenericHID(int port) { - if (port < 0 || port >= DriverStation::JOYSTICK_PORTS) { + if (port < 0 || port >= wpi::internal::DriverStationBackend::JOYSTICK_PORTS) { throw WPILIB_MakeError(warn::BadJoystickIndex, "port {} out of range", port); } @@ -22,15 +22,17 @@ GenericHID::GenericHID(int port) { } bool GenericHID::GetRawButton(int button) const { - return DriverStation::GetStickButton(m_port, button); + return wpi::internal::DriverStationBackend::GetStickButton(m_port, button); } bool GenericHID::GetRawButtonPressed(int button) { - return DriverStation::GetStickButtonPressed(m_port, button); + return wpi::internal::DriverStationBackend::GetStickButtonPressed(m_port, + button); } bool GenericHID::GetRawButtonReleased(int button) { - return DriverStation::GetStickButtonReleased(m_port, button); + return wpi::internal::DriverStationBackend::GetStickButtonReleased(m_port, + button); } BooleanEvent GenericHID::Button(int button, EventLoop* loop) const { @@ -39,58 +41,57 @@ BooleanEvent GenericHID::Button(int button, EventLoop* loop) const { } double GenericHID::GetRawAxis(int axis) const { - return DriverStation::GetStickAxis(m_port, axis); + return wpi::internal::DriverStationBackend::GetStickAxis(m_port, axis); } -DriverStation::POVDirection GenericHID::GetPOV(int pov) const { - return DriverStation::GetStickPOV(m_port, pov); +POVDirection GenericHID::GetPOV(int pov) const { + return wpi::internal::DriverStationBackend::GetStickPOV(m_port, pov); } -BooleanEvent GenericHID::POV(DriverStation::POVDirection angle, - EventLoop* loop) const { +BooleanEvent GenericHID::POV(POVDirection angle, EventLoop* loop) const { return POV(0, angle, loop); } -BooleanEvent GenericHID::POV(int pov, DriverStation::POVDirection angle, +BooleanEvent GenericHID::POV(int pov, POVDirection angle, EventLoop* loop) const { return BooleanEvent( loop, [this, pov, angle] { return this->GetPOV(pov) == angle; }); } BooleanEvent GenericHID::POVUp(EventLoop* loop) const { - return POV(DriverStation::POVDirection::UP, loop); + return POV(POVDirection::UP, loop); } BooleanEvent GenericHID::POVUpRight(EventLoop* loop) const { - return POV(DriverStation::POVDirection::UP_RIGHT, loop); + return POV(POVDirection::UP_RIGHT, loop); } BooleanEvent GenericHID::POVRight(EventLoop* loop) const { - return POV(DriverStation::POVDirection::RIGHT, loop); + return POV(POVDirection::RIGHT, loop); } BooleanEvent GenericHID::POVDownRight(EventLoop* loop) const { - return POV(DriverStation::POVDirection::DOWN_RIGHT, loop); + return POV(POVDirection::DOWN_RIGHT, loop); } BooleanEvent GenericHID::POVDown(EventLoop* loop) const { - return POV(DriverStation::POVDirection::DOWN, loop); + return POV(POVDirection::DOWN, loop); } BooleanEvent GenericHID::POVDownLeft(EventLoop* loop) const { - return POV(DriverStation::POVDirection::DOWN_LEFT, loop); + return POV(POVDirection::DOWN_LEFT, loop); } BooleanEvent GenericHID::POVLeft(EventLoop* loop) const { - return POV(DriverStation::POVDirection::LEFT, loop); + return POV(POVDirection::LEFT, loop); } BooleanEvent GenericHID::POVUpLeft(EventLoop* loop) const { - return POV(DriverStation::POVDirection::UP_LEFT, loop); + return POV(POVDirection::UP_LEFT, loop); } BooleanEvent GenericHID::POVCenter(EventLoop* loop) const { - return POV(DriverStation::POVDirection::CENTER, loop); + return POV(POVDirection::CENTER, loop); } BooleanEvent GenericHID::AxisLessThan(int axis, double threshold, @@ -108,44 +109,46 @@ BooleanEvent GenericHID::AxisGreaterThan(int axis, double threshold, } int GenericHID::GetAxesMaximumIndex() const { - return DriverStation::GetStickAxesMaximumIndex(m_port); + return wpi::internal::DriverStationBackend::GetStickAxesMaximumIndex(m_port); } int GenericHID::GetAxesAvailable() const { - return DriverStation::GetStickAxesAvailable(m_port); + return wpi::internal::DriverStationBackend::GetStickAxesAvailable(m_port); } int GenericHID::GetPOVsMaximumIndex() const { - return DriverStation::GetStickPOVsMaximumIndex(m_port); + return wpi::internal::DriverStationBackend::GetStickPOVsMaximumIndex(m_port); } int GenericHID::GetPOVsAvailable() const { - return DriverStation::GetStickPOVsAvailable(m_port); + return wpi::internal::DriverStationBackend::GetStickPOVsAvailable(m_port); } int GenericHID::GetButtonsMaximumIndex() const { - return DriverStation::GetStickButtonsMaximumIndex(m_port); + return wpi::internal::DriverStationBackend::GetStickButtonsMaximumIndex( + m_port); } uint64_t GenericHID::GetButtonsAvailable() const { - return DriverStation::GetStickButtonsAvailable(m_port); + return wpi::internal::DriverStationBackend::GetStickButtonsAvailable(m_port); } bool GenericHID::IsConnected() const { - return DriverStation::IsJoystickConnected(m_port); + return wpi::internal::DriverStationBackend::IsJoystickConnected(m_port); } GenericHID::HIDType GenericHID::GetGamepadType() const { - return static_cast(DriverStation::GetJoystickGamepadType(m_port)); + return static_cast( + wpi::internal::DriverStationBackend::GetJoystickGamepadType(m_port)); } GenericHID::SupportedOutputs GenericHID::GetSupportedOutputs() const { return static_cast( - DriverStation::GetJoystickSupportedOutputs(m_port)); + wpi::internal::DriverStationBackend::GetJoystickSupportedOutputs(m_port)); } std::string GenericHID::GetName() const { - return DriverStation::GetJoystickName(m_port); + return wpi::internal::DriverStationBackend::GetJoystickName(m_port); } int GenericHID::GetPort() const { @@ -178,11 +181,11 @@ void GenericHID::SetRumble(RumbleType type, double value) { } bool GenericHID::GetTouchpadFingerAvailable(int touchpad, int finger) const { - return DriverStation::GetStickTouchpadFingerAvailable(m_port, touchpad, - finger); + return wpi::internal::DriverStationBackend::GetStickTouchpadFingerAvailable( + m_port, touchpad, finger); } -DriverStation::TouchpadFinger GenericHID::GetTouchpadFinger(int touchpad, - int finger) const { - return DriverStation::GetStickTouchpadFinger(m_port, touchpad, finger); +TouchpadFinger GenericHID::GetTouchpadFinger(int touchpad, int finger) const { + return wpi::internal::DriverStationBackend::GetStickTouchpadFinger( + m_port, touchpad, finger); } diff --git a/wpilibc/src/main/native/cpp/driverstation/DriverStation.cpp b/wpilibc/src/main/native/cpp/driverstation/internal/DriverStationBackend.cpp similarity index 87% rename from wpilibc/src/main/native/cpp/driverstation/DriverStation.cpp rename to wpilibc/src/main/native/cpp/driverstation/internal/DriverStationBackend.cpp index ecc01c1f64..0d64153be4 100644 --- a/wpilibc/src/main/native/cpp/driverstation/DriverStation.cpp +++ b/wpilibc/src/main/native/cpp/driverstation/internal/DriverStationBackend.cpp @@ -2,7 +2,7 @@ // 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. -#include "wpi/driverstation/DriverStation.hpp" +#include "wpi/driverstation/internal/DriverStationBackend.hpp" #include @@ -40,6 +40,7 @@ #include "wpi/util/timestamp.hpp" using namespace wpi; +using namespace wpi::internal; static constexpr int availableToCount(uint64_t available) { return 64 - std::countl_zero(available); @@ -136,7 +137,8 @@ class DataLogSender { wpi::log::StringLogEntry m_logOpMode; bool m_logJoysticks; - std::array m_joysticks; + std::array + m_joysticks; }; struct Instance { @@ -149,10 +151,12 @@ struct Instance { // Joystick button rising/falling edge flags wpi::util::mutex buttonEdgeMutex; - std::array + std::array previousButtonStates; - std::array joystickButtonsPressed; - std::array joystickButtonsReleased; + std::array + joystickButtonsPressed; + std::array + joystickButtonsReleased; bool silenceJoystickWarning = false; @@ -211,7 +215,7 @@ Instance::Instance() { // All joysticks should default to having zero axes, povs and buttons, so // uninitialized memory doesn't get sent to motor controllers. - for (unsigned int i = 0; i < DriverStation::JOYSTICK_PORTS; i++) { + for (unsigned int i = 0; i < DriverStationBackend::JOYSTICK_PORTS; i++) { joystickButtonsPressed[i] = 0; joystickButtonsReleased[i] = 0; previousButtonStates[i].available = 0; @@ -225,7 +229,7 @@ Instance::~Instance() { } } -bool DriverStation::GetStickButton(int stick, int button) { +bool DriverStationBackend::GetStickButton(int stick, int button) { if (stick < 0 || stick >= JOYSTICK_PORTS) { WPILIB_ReportError(warn::BadJoystickIndex, "stick {} out of range", stick); return false; @@ -250,8 +254,8 @@ bool DriverStation::GetStickButton(int stick, int button) { return (buttons.buttons & mask) != 0; } -std::optional DriverStation::GetStickButtonIfAvailable(int stick, - int button) { +std::optional DriverStationBackend::GetStickButtonIfAvailable( + int stick, int button) { if (stick < 0 || stick >= JOYSTICK_PORTS) { WPILIB_ReportError(warn::BadJoystickIndex, "stick {} out of range", stick); return false; @@ -274,7 +278,7 @@ std::optional DriverStation::GetStickButtonIfAvailable(int stick, return (buttons.buttons & mask) != 0; } -bool DriverStation::GetStickButtonPressed(int stick, int button) { +bool DriverStationBackend::GetStickButtonPressed(int stick, int button) { if (stick < 0 || stick >= JOYSTICK_PORTS) { WPILIB_ReportError(warn::BadJoystickIndex, "stick {} out of range", stick); return false; @@ -305,7 +309,7 @@ bool DriverStation::GetStickButtonPressed(int stick, int button) { return false; } -bool DriverStation::GetStickButtonReleased(int stick, int button) { +bool DriverStationBackend::GetStickButtonReleased(int stick, int button) { if (stick < 0 || stick >= JOYSTICK_PORTS) { WPILIB_ReportError(warn::BadJoystickIndex, "stick {} out of range", stick); return false; @@ -336,7 +340,7 @@ bool DriverStation::GetStickButtonReleased(int stick, int button) { return false; } -double DriverStation::GetStickAxis(int stick, int axis) { +double DriverStationBackend::GetStickAxis(int stick, int axis) { if (stick < 0 || stick >= JOYSTICK_PORTS) { WPILIB_ReportError(warn::BadJoystickIndex, "stick {} out of range", stick); return 0.0; @@ -360,8 +364,9 @@ double DriverStation::GetStickAxis(int stick, int axis) { return axes.axes[axis]; } -DriverStation::TouchpadFinger DriverStation::GetStickTouchpadFinger( - int stick, int touchpad, int finger) { +TouchpadFinger DriverStationBackend::GetStickTouchpadFinger(int stick, + int touchpad, + int finger) { if (stick < 0 || stick >= JOYSTICK_PORTS) { WPILIB_ReportError(warn::BadJoystickIndex, "stick {} out of range", stick); return TouchpadFinger{false, 0.0f, 0.0f}; @@ -396,8 +401,9 @@ DriverStation::TouchpadFinger DriverStation::GetStickTouchpadFinger( return TouchpadFinger{false, 0.0f, 0.0f}; } -bool DriverStation::GetStickTouchpadFingerAvailable(int stick, int touchpad, - int finger) { +bool DriverStationBackend::GetStickTouchpadFingerAvailable(int stick, + int touchpad, + int finger) { if (stick < 0 || stick >= JOYSTICK_PORTS) { WPILIB_ReportError(warn::BadJoystickIndex, "stick {} out of range", stick); return false; @@ -425,8 +431,8 @@ bool DriverStation::GetStickTouchpadFingerAvailable(int stick, int touchpad, return false; } -std::optional DriverStation::GetStickAxisIfAvailable(int stick, - int axis) { +std::optional DriverStationBackend::GetStickAxisIfAvailable(int stick, + int axis) { if (stick < 0 || stick >= JOYSTICK_PORTS) { WPILIB_ReportError(warn::BadJoystickIndex, "stick {} out of range", stick); return 0.0; @@ -448,7 +454,7 @@ std::optional DriverStation::GetStickAxisIfAvailable(int stick, return axes.axes[axis]; } -DriverStation::POVDirection DriverStation::GetStickPOV(int stick, int pov) { +POVDirection DriverStationBackend::GetStickPOV(int stick, int pov) { if (stick < 0 || stick >= JOYSTICK_PORTS) { WPILIB_ReportError(warn::BadJoystickIndex, "stick {} out of range", stick); return POVDirection::CENTER; @@ -472,7 +478,7 @@ DriverStation::POVDirection DriverStation::GetStickPOV(int stick, int pov) { return static_cast(povs.povs[pov]); } -uint64_t DriverStation::GetStickButtons(int stick) { +uint64_t DriverStationBackend::GetStickButtons(int stick) { if (stick < 0 || stick >= JOYSTICK_PORTS) { WPILIB_ReportError(warn::BadJoystickIndex, "stick {} out of range", stick); return 0; @@ -484,11 +490,11 @@ uint64_t DriverStation::GetStickButtons(int stick) { return buttons.buttons; } -int DriverStation::GetStickAxesMaximumIndex(int stick) { +int DriverStationBackend::GetStickAxesMaximumIndex(int stick) { return availableToCount(GetStickAxesAvailable(stick)); } -int DriverStation::GetStickAxesAvailable(int stick) { +int DriverStationBackend::GetStickAxesAvailable(int stick) { if (stick < 0 || stick >= JOYSTICK_PORTS) { WPILIB_ReportError(warn::BadJoystickIndex, "stick {} out of range", stick); return 0; @@ -500,11 +506,11 @@ int DriverStation::GetStickAxesAvailable(int stick) { return axes.available; } -int DriverStation::GetStickPOVsMaximumIndex(int stick) { +int DriverStationBackend::GetStickPOVsMaximumIndex(int stick) { return availableToCount(GetStickPOVsAvailable(stick)); } -int DriverStation::GetStickPOVsAvailable(int stick) { +int DriverStationBackend::GetStickPOVsAvailable(int stick) { if (stick < 0 || stick >= JOYSTICK_PORTS) { WPILIB_ReportError(warn::BadJoystickIndex, "stick {} out of range", stick); return 0; @@ -516,11 +522,11 @@ int DriverStation::GetStickPOVsAvailable(int stick) { return povs.available; } -int DriverStation::GetStickButtonsMaximumIndex(int stick) { +int DriverStationBackend::GetStickButtonsMaximumIndex(int stick) { return availableToCount(GetStickButtonsAvailable(stick)); } -uint64_t DriverStation::GetStickButtonsAvailable(int stick) { +uint64_t DriverStationBackend::GetStickButtonsAvailable(int stick) { if (stick < 0 || stick >= JOYSTICK_PORTS) { WPILIB_ReportError(warn::BadJoystickIndex, "stick {} out of range", stick); return 0; @@ -532,7 +538,7 @@ uint64_t DriverStation::GetStickButtonsAvailable(int stick) { return buttons.available; } -bool DriverStation::GetJoystickIsGamepad(int stick) { +bool DriverStationBackend::GetJoystickIsGamepad(int stick) { if (stick < 0 || stick >= JOYSTICK_PORTS) { WPILIB_ReportError(warn::BadJoystickIndex, "stick {} out of range", stick); return false; @@ -544,7 +550,7 @@ bool DriverStation::GetJoystickIsGamepad(int stick) { return static_cast(descriptor.isGamepad); } -int DriverStation::GetJoystickGamepadType(int stick) { +int DriverStationBackend::GetJoystickGamepadType(int stick) { if (stick < 0 || stick >= JOYSTICK_PORTS) { WPILIB_ReportError(warn::BadJoystickIndex, "stick {} out of range", stick); return -1; @@ -556,7 +562,7 @@ int DriverStation::GetJoystickGamepadType(int stick) { return static_cast(descriptor.gamepadType); } -int DriverStation::GetJoystickSupportedOutputs(int stick) { +int DriverStationBackend::GetJoystickSupportedOutputs(int stick) { if (stick < 0 || stick >= JOYSTICK_PORTS) { WPILIB_ReportError(warn::BadJoystickIndex, "stick {} out of range", stick); return 0; @@ -568,7 +574,7 @@ int DriverStation::GetJoystickSupportedOutputs(int stick) { return static_cast(descriptor.supportedOutputs); } -std::string DriverStation::GetJoystickName(int stick) { +std::string DriverStationBackend::GetJoystickName(int stick) { if (stick < 0 || stick >= JOYSTICK_PORTS) { WPILIB_ReportError(warn::BadJoystickIndex, "stick {} out of range", stick); } @@ -579,7 +585,7 @@ std::string DriverStation::GetJoystickName(int stick) { return descriptor.name; } -bool DriverStation::IsJoystickConnected(int stick) { +bool DriverStationBackend::IsJoystickConnected(int stick) { return GetStickAxesAvailable(stick) != 0 || GetStickButtonsAvailable(stick) != 0 || GetStickPOVsAvailable(stick) != 0; @@ -624,23 +630,23 @@ static int32_t ConvertColorToInt(const wpi::util::Color& color) { (static_cast(color.blue * 255) & 0xff); } -int64_t DriverStation::AddOpMode(RobotMode mode, std::string_view name, - std::string_view group, - std::string_view description, - const wpi::util::Color& textColor, - const wpi::util::Color& backgroundColor) { +int64_t DriverStationBackend::AddOpMode( + RobotMode mode, std::string_view name, std::string_view group, + std::string_view description, const wpi::util::Color& textColor, + const wpi::util::Color& backgroundColor) { return DoAddOpMode(mode, name, group, description, ConvertColorToInt(textColor), ConvertColorToInt(backgroundColor)); } -int64_t DriverStation::AddOpMode(RobotMode mode, std::string_view name, - std::string_view group, - std::string_view description) { +int64_t DriverStationBackend::AddOpMode(RobotMode mode, std::string_view name, + std::string_view group, + std::string_view description) { return DoAddOpMode(mode, name, group, description, -1, -1); } -int64_t DriverStation::RemoveOpMode(RobotMode mode, std::string_view name) { +int64_t DriverStationBackend::RemoveOpMode(RobotMode mode, + std::string_view name) { if (wpi::util::trim(name).empty()) { return 0; } @@ -662,7 +668,7 @@ int64_t DriverStation::RemoveOpMode(RobotMode mode, std::string_view name) { return 0; } -void DriverStation::PublishOpModes() { +void DriverStationBackend::PublishOpModes() { auto& inst = ::GetInstance(); std::scoped_lock lock{inst.opModeMutex}; std::vector options; @@ -673,19 +679,19 @@ void DriverStation::PublishOpModes() { HAL_SetOpModeOptions(options.data(), options.size()); } -void DriverStation::ClearOpModes() { +void DriverStationBackend::ClearOpModes() { auto& inst = ::GetInstance(); std::scoped_lock lock{inst.opModeMutex}; inst.opModes.clear(); HAL_SetOpModeOptions(nullptr, 0); } -void DriverStation::ObserveUserProgramStarting() { +void DriverStationBackend::ObserveUserProgramStarting() { ::GetInstance().userProgramStarted = true; HAL_ObserveUserProgramStarting(); } -int64_t DriverStation::GetOpModeId() { +int64_t DriverStationBackend::GetOpModeId() { if (!::GetInstance().userProgramStarted) { return 0; } @@ -693,7 +699,7 @@ int64_t DriverStation::GetOpModeId() { return GetControlWord().GetOpModeId(); } -std::string DriverStation::GetOpMode() { +std::string DriverStationBackend::GetOpMode() { if (!::GetInstance().userProgramStarted) { return ""; } @@ -701,7 +707,7 @@ std::string DriverStation::GetOpMode() { return GetInstance().OpModeToString(GetOpModeId()); } -std::optional DriverStation::GetGameData() { +std::optional DriverStationBackend::GetGameData() { HAL_GameData info; HAL_GetGameData(&info); std::string_view gameDataView{reinterpret_cast(info.gameData)}; @@ -711,31 +717,31 @@ std::optional DriverStation::GetGameData() { return std::string(gameDataView); } -std::string DriverStation::GetEventName() { +std::string DriverStationBackend::GetEventName() { HAL_MatchInfo info; HAL_GetMatchInfo(&info); return info.eventName; } -DriverStation::MatchType DriverStation::GetMatchType() { +MatchType DriverStationBackend::GetMatchType() { HAL_MatchInfo info; HAL_GetMatchInfo(&info); - return static_cast(info.matchType); + return static_cast(info.matchType); } -int DriverStation::GetMatchNumber() { +int DriverStationBackend::GetMatchNumber() { HAL_MatchInfo info; HAL_GetMatchInfo(&info); return info.matchNumber; } -int DriverStation::GetReplayNumber() { +int DriverStationBackend::GetReplayNumber() { HAL_MatchInfo info; HAL_GetMatchInfo(&info); return info.replayNumber; } -std::optional DriverStation::GetAlliance() { +std::optional DriverStationBackend::GetAlliance() { int32_t status = 0; auto allianceStationID = HAL_GetAllianceStation(&status); switch (allianceStationID) { @@ -752,7 +758,7 @@ std::optional DriverStation::GetAlliance() { } } -std::optional DriverStation::GetLocation() { +std::optional DriverStationBackend::GetLocation() { int32_t status = 0; auto allianceStationID = HAL_GetAllianceStation(&status); switch (allianceStationID) { @@ -770,12 +776,12 @@ std::optional DriverStation::GetLocation() { } } -wpi::units::second_t DriverStation::GetMatchTime() { +wpi::units::second_t DriverStationBackend::GetMatchTime() { int32_t status = 0; return wpi::units::second_t{HAL_GetMatchTime(&status)}; } -double DriverStation::GetBatteryVoltage() { +double DriverStationBackend::GetBatteryVoltage() { int32_t status = 0; double voltage = HAL_GetVinVoltage(&status); WPILIB_CheckErrorStatus(status, "getVinVoltage"); @@ -789,7 +795,7 @@ double DriverStation::GetBatteryVoltage() { * If no new data exists, it will just be returned, otherwise * the data will be copied from the DS polling loop. */ -void DriverStation::RefreshData() { +void DriverStationBackend::RefreshData() { HAL_RefreshDSData(); auto& inst = ::GetInstance(); { @@ -797,7 +803,7 @@ void DriverStation::RefreshData() { HAL_JoystickButtons currentButtons; std::unique_lock lock(inst.buttonEdgeMutex); - for (int32_t i = 0; i < DriverStation::JOYSTICK_PORTS; i++) { + for (int32_t i = 0; i < DriverStationBackend::JOYSTICK_PORTS; i++) { HAL_GetJoystickButtons(i, ¤tButtons); // If buttons weren't pressed and are now, set flags in m_buttonsPressed @@ -820,25 +826,28 @@ void DriverStation::RefreshData() { } } -void DriverStation::ProvideRefreshedDataEventHandle(WPI_EventHandle handle) { +void DriverStationBackend::ProvideRefreshedDataEventHandle( + WPI_EventHandle handle) { auto& inst = ::GetInstance(); inst.refreshEvents.Add(handle); } -void DriverStation::RemoveRefreshedDataEventHandle(WPI_EventHandle handle) { +void DriverStationBackend::RemoveRefreshedDataEventHandle( + WPI_EventHandle handle) { auto& inst = ::GetInstance(); inst.refreshEvents.Remove(handle); } -void DriverStation::SilenceJoystickConnectionWarning(bool silence) { +void DriverStationBackend::SilenceJoystickConnectionWarning(bool silence) { ::GetInstance().silenceJoystickWarning = silence; } -bool DriverStation::IsJoystickConnectionWarningSilenced() { +bool DriverStationBackend::IsJoystickConnectionWarningSilenced() { return !IsFMSAttached() && ::GetInstance().silenceJoystickWarning; } -void DriverStation::StartDataLog(wpi::log::DataLog& log, bool logJoysticks) { +void DriverStationBackend::StartDataLog(wpi::log::DataLog& log, + bool logJoysticks) { auto& inst = ::GetInstance(); // Note: cannot safely replace, because we wouldn't know when to delete the // "old" one. Instead do a compare and exchange with nullptr. We check first @@ -859,10 +868,10 @@ void DriverStation::StartDataLog(wpi::log::DataLog& log, bool logJoysticks) { void ReportJoystickWarningV(int stick, fmt::string_view format, fmt::format_args args) { auto& inst = GetInstance(); - if (DriverStation::IsFMSAttached() || !inst.silenceJoystickWarning) { + if (DriverStationBackend::IsFMSAttached() || !inst.silenceJoystickWarning) { auto currentTime = Timer::GetTimestamp(); if (currentTime > inst.nextMessageTime) { - if (DriverStation::IsJoystickConnected(stick)) { + if (DriverStationBackend::IsJoystickConnected(stick)) { ReportErrorV(warn::Warning, "", 0, "", format, args); } else { ReportError( diff --git a/wpilibc/src/main/native/cpp/framework/IterativeRobotBase.cpp b/wpilibc/src/main/native/cpp/framework/IterativeRobotBase.cpp index 8dab4600b9..d6efcbf073 100644 --- a/wpilibc/src/main/native/cpp/framework/IterativeRobotBase.cpp +++ b/wpilibc/src/main/native/cpp/framework/IterativeRobotBase.cpp @@ -4,7 +4,8 @@ #include "wpi/framework/IterativeRobotBase.hpp" -#include "wpi/driverstation/DriverStation.hpp" +#include "wpi/driverstation/RobotState.hpp" +#include "wpi/driverstation/internal/DriverStationBackend.hpp" #include "wpi/hal/DriverStation.h" #include "wpi/hal/DriverStationTypes.h" #include "wpi/nt/NetworkTableInstance.hpp" @@ -91,7 +92,7 @@ wpi::units::second_t IterativeRobotBase::GetPeriod() const { } void IterativeRobotBase::LoopFunc() { - DriverStation::RefreshData(); + wpi::internal::DriverStationBackend::RefreshData(); m_watchdog.Reset(); // Get current mode; treat disabled as unknown diff --git a/wpilibc/src/main/native/cpp/framework/OpModeRobot.cpp b/wpilibc/src/main/native/cpp/framework/OpModeRobot.cpp index 05680fee47..e90c1c7672 100644 --- a/wpilibc/src/main/native/cpp/framework/OpModeRobot.cpp +++ b/wpilibc/src/main/native/cpp/framework/OpModeRobot.cpp @@ -12,7 +12,8 @@ #include -#include "wpi/driverstation/DriverStation.hpp" +#include "wpi/driverstation/RobotState.hpp" +#include "wpi/driverstation/internal/DriverStationBackend.hpp" #include "wpi/hal/DriverStation.h" #include "wpi/hal/DriverStationTypes.h" #include "wpi/hal/HAL.h" @@ -54,10 +55,11 @@ void OpModeRobotBase::AddPeriodic(std::function callback, } void OpModeRobotBase::LoopFunc() { - DriverStation::RefreshData(); + wpi::internal::DriverStationBackend::RefreshData(); // Get current enabled state and opmode - const hal::ControlWord word = DriverStation::GetControlWord(); + const hal::ControlWord word = + wpi::internal::DriverStationBackend::GetControlWord(); m_watchdog.Reset(); const bool enabled = word.IsEnabled(); int64_t modeId = word.IsDSAttached() ? word.GetOpModeId() : 0; @@ -194,7 +196,7 @@ void OpModeRobotBase::StartCompetition() { } // Tell the DS that the robot is ready to be enabled - DriverStation::ObserveUserProgramStarting(); + wpi::internal::DriverStationBackend::ObserveUserProgramStarting(); // Loop forever, calling the callback system which handles periodic functions while (true) { @@ -215,8 +217,8 @@ void OpModeRobotBase::AddOpModeFactory( std::string_view group, std::string_view description, const wpi::util::Color& textColor, const wpi::util::Color& backgroundColor) { - int64_t id = DriverStation::AddOpMode(mode, name, group, description, - textColor, backgroundColor); + int64_t id = RobotState::AddOpMode(mode, name, group, description, textColor, + backgroundColor); if (id != 0) { m_opModes[id] = OpModeData{std::string{name}, std::move(factory)}; } @@ -226,24 +228,24 @@ void OpModeRobotBase::AddOpModeFactory(OpModeFactory factory, RobotMode mode, std::string_view name, std::string_view group, std::string_view description) { - int64_t id = DriverStation::AddOpMode(mode, name, group, description); + int64_t id = RobotState::AddOpMode(mode, name, group, description); if (id != 0) { m_opModes[id] = OpModeData{std::string{name}, std::move(factory)}; } } void OpModeRobotBase::RemoveOpMode(RobotMode mode, std::string_view name) { - int64_t id = DriverStation::RemoveOpMode(mode, name); + int64_t id = RobotState::RemoveOpMode(mode, name); if (id != 0) { m_opModes.erase(id); } } void OpModeRobotBase::PublishOpModes() { - DriverStation::PublishOpModes(); + RobotState::PublishOpModes(); } void OpModeRobotBase::ClearOpModes() { - DriverStation::ClearOpModes(); + RobotState::ClearOpModes(); m_opModes.clear(); } diff --git a/wpilibc/src/main/native/cpp/framework/TimedRobot.cpp b/wpilibc/src/main/native/cpp/framework/TimedRobot.cpp index 14307f4136..a4dc647ebf 100644 --- a/wpilibc/src/main/native/cpp/framework/TimedRobot.cpp +++ b/wpilibc/src/main/native/cpp/framework/TimedRobot.cpp @@ -10,6 +10,7 @@ #include #include "wpi/driverstation/DriverStation.hpp" +#include "wpi/driverstation/internal/DriverStationBackend.hpp" #include "wpi/hal/DriverStation.hpp" #include "wpi/hal/UsageReporting.hpp" #include "wpi/system/Errors.hpp" @@ -24,7 +25,7 @@ void TimedRobot::StartCompetition() { // Tell the DS that the robot is ready to be enabled std::puts("\n********** Robot program startup complete **********"); - DriverStation::ObserveUserProgramStarting(); + wpi::internal::DriverStationBackend::ObserveUserProgramStarting(); // Loop forever, calling the appropriate mode-dependent function while (true) { diff --git a/wpilibc/src/main/native/cpp/hardware/motor/MotorSafety.cpp b/wpilibc/src/main/native/cpp/hardware/motor/MotorSafety.cpp index c42d64f037..2461a1ad7f 100644 --- a/wpilibc/src/main/native/cpp/hardware/motor/MotorSafety.cpp +++ b/wpilibc/src/main/native/cpp/hardware/motor/MotorSafety.cpp @@ -6,7 +6,7 @@ #include -#include "wpi/driverstation/DriverStation.hpp" +#include "wpi/driverstation/RobotState.hpp" #include "wpi/hal/DriverStation.h" #include "wpi/hal/DriverStationTypes.h" #include "wpi/system/Errors.hpp" @@ -153,7 +153,7 @@ void MotorSafety::Check() { stopTime = m_stopTime; } - if (!enabled || DriverStation::IsDisabled() || DriverStation::IsTest()) { + if (!enabled || RobotState::IsDisabled() || RobotState::IsTest()) { return; } diff --git a/wpilibc/src/main/native/cpp/internal/DriverStationModeThread.cpp b/wpilibc/src/main/native/cpp/internal/DriverStationModeThread.cpp index 7f28ee25ec..68055f6283 100644 --- a/wpilibc/src/main/native/cpp/internal/DriverStationModeThread.cpp +++ b/wpilibc/src/main/native/cpp/internal/DriverStationModeThread.cpp @@ -4,7 +4,7 @@ #include "wpi/internal/DriverStationModeThread.hpp" -#include "wpi/driverstation/DriverStation.hpp" +#include "wpi/driverstation/internal/DriverStationBackend.hpp" #include "wpi/hal/DriverStation.h" #include "wpi/util/Synchronization.hpp" @@ -33,7 +33,7 @@ void DriverStationModeThread::Run() { if (!m_keepAlive) { break; } - wpi::DriverStation::RefreshData(); + wpi::internal::DriverStationBackend::RefreshData(); HAL_ObserveUserProgram({.value = m_userControlWord}); } } diff --git a/wpilibc/src/main/native/cpp/simulation/DriverStationSim.cpp b/wpilibc/src/main/native/cpp/simulation/DriverStationSim.cpp index b3e12dd883..7cc6ca06cd 100644 --- a/wpilibc/src/main/native/cpp/simulation/DriverStationSim.cpp +++ b/wpilibc/src/main/native/cpp/simulation/DriverStationSim.cpp @@ -6,7 +6,7 @@ #include -#include "wpi/driverstation/DriverStation.hpp" +#include "wpi/driverstation/internal/DriverStationBackend.hpp" #include "wpi/hal/DriverStation.h" #include "wpi/hal/simulation/DriverStationData.h" #include "wpi/hal/simulation/MockHooks.h" @@ -175,7 +175,7 @@ void DriverStationSim::NotifyNewData() { HALSIM_NotifyDriverStationNewData(); wpi::util::WaitForObject(waitEvent.GetHandle()); HAL_RemoveNewDataEventHandle(waitEvent.GetHandle()); - wpi::DriverStation::RefreshData(); + wpi::internal::DriverStationBackend::RefreshData(); } void DriverStationSim::SetSendError(bool shouldSend) { @@ -232,8 +232,7 @@ void DriverStationSim::SetJoystickAxis(int stick, int axis, double value) { HALSIM_SetJoystickAxis(stick, axis, value); } -void DriverStationSim::SetJoystickPOV(int stick, int pov, - DriverStation::POVDirection value) { +void DriverStationSim::SetJoystickPOV(int stick, int pov, POVDirection value) { HALSIM_SetJoystickPOV(stick, pov, static_cast(value)); } @@ -313,7 +312,7 @@ void DriverStationSim::SetEventName(std::string_view name) { HALSIM_SetEventName(&str); } -void DriverStationSim::SetMatchType(DriverStation::MatchType type) { +void DriverStationSim::SetMatchType(MatchType type) { HALSIM_SetMatchType(static_cast(static_cast(type))); } diff --git a/wpilibc/src/main/native/cpp/simulation/GenericHIDSim.cpp b/wpilibc/src/main/native/cpp/simulation/GenericHIDSim.cpp index 851799a009..b4edaecb2a 100644 --- a/wpilibc/src/main/native/cpp/simulation/GenericHIDSim.cpp +++ b/wpilibc/src/main/native/cpp/simulation/GenericHIDSim.cpp @@ -4,8 +4,8 @@ #include "wpi/simulation/GenericHIDSim.hpp" -#include "wpi/driverstation/DriverStation.hpp" #include "wpi/driverstation/GenericHID.hpp" +#include "wpi/driverstation/internal/DriverStationBackend.hpp" #include "wpi/simulation/DriverStationSim.hpp" using namespace wpi; @@ -28,11 +28,11 @@ void GenericHIDSim::SetRawAxis(int axis, double value) { DriverStationSim::SetJoystickAxis(m_port, axis, value); } -void GenericHIDSim::SetPOV(int pov, DriverStation::POVDirection value) { +void GenericHIDSim::SetPOV(int pov, POVDirection value) { DriverStationSim::SetJoystickPOV(m_port, pov, value); } -void GenericHIDSim::SetPOV(DriverStation::POVDirection value) { +void GenericHIDSim::SetPOV(POVDirection value) { SetPOV(0, value); } diff --git a/wpilibc/src/main/native/cpp/system/DataLogManager.cpp b/wpilibc/src/main/native/cpp/system/DataLogManager.cpp index c7c6d608f4..7ea75b67d4 100644 --- a/wpilibc/src/main/native/cpp/system/DataLogManager.cpp +++ b/wpilibc/src/main/native/cpp/system/DataLogManager.cpp @@ -15,7 +15,9 @@ #include "wpi/datalog/DataLog.hpp" #include "wpi/datalog/DataLogBackgroundWriter.hpp" #include "wpi/datalog/FileLogger.hpp" -#include "wpi/driverstation/DriverStation.hpp" +#include "wpi/driverstation/MatchState.hpp" +#include "wpi/driverstation/RobotState.hpp" +#include "wpi/driverstation/internal/DriverStationBackend.hpp" #include "wpi/framework/RobotBase.hpp" #include "wpi/hal/UsageReporting.hpp" #include "wpi/nt/NetworkTableInstance.hpp" @@ -190,7 +192,8 @@ void Thread::Main() { "{\"source\":\"DataLogManager\",\"format\":\"time_t_us\"}"}; wpi::util::Event newDataEvent; - DriverStation::ProvideRefreshedDataEventHandle(newDataEvent.GetHandle()); + wpi::internal::DriverStationBackend::ProvideRefreshedDataEventHandle( + newDataEvent.GetHandle()); for (;;) { bool timedOut = false; @@ -218,7 +221,7 @@ void Thread::Main() { if (!dsRenamed) { // track DS attach - if (DriverStation::IsDSAttached()) { + if (RobotState::IsDSAttached()) { ++dsAttachCount; } else { dsAttachCount = 0; @@ -236,7 +239,7 @@ void Thread::Main() { if (!fmsRenamed) { // track FMS attach - if (DriverStation::IsFMSAttached()) { + if (RobotState::IsFMSAttached()) { ++fmsAttachCount; } else { fmsAttachCount = 0; @@ -244,18 +247,18 @@ void Thread::Main() { if (fmsAttachCount > 250) { // 5 seconds // match info comes through TCP, so we need to double-check we've // actually received it - auto matchType = DriverStation::GetMatchType(); - if (matchType != DriverStation::MatchType::NONE) { + auto matchType = MatchState::GetMatchType(); + if (matchType != wpi::MatchType::NONE) { // rename per match info char matchTypeChar; switch (matchType) { - case DriverStation::MatchType::PRACTICE: + case wpi::MatchType::PRACTICE: matchTypeChar = 'P'; break; - case DriverStation::MatchType::QUALIFICATION: + case wpi::MatchType::QUALIFICATION: matchTypeChar = 'Q'; break; - case DriverStation::MatchType::ELIMINATION: + case wpi::MatchType::ELIMINATION: matchTypeChar = 'E'; break; default: @@ -265,8 +268,8 @@ void Thread::Main() { auto now = std::chrono::system_clock::now(); m_log.SetFilename( fmt::format("WPILIB_{:%Y%m%d_%H%M%S}_{}_{}{}.wpilog", now, - DriverStation::GetEventName(), matchTypeChar, - DriverStation::GetMatchNumber())); + MatchState::GetEventName(), matchTypeChar, + MatchState::GetMatchNumber())); fmsRenamed = true; dsRenamed = true; // don't override FMS rename } @@ -282,7 +285,8 @@ void Thread::Main() { } } } - DriverStation::RemoveRefreshedDataEventHandle(newDataEvent.GetHandle()); + wpi::internal::DriverStationBackend::RemoveRefreshedDataEventHandle( + newDataEvent.GetHandle()); } void Thread::StartNTLog() { diff --git a/wpilibc/src/main/native/cpp/system/Timer.cpp b/wpilibc/src/main/native/cpp/system/Timer.cpp index f6a3d5aff4..39f15ac662 100644 --- a/wpilibc/src/main/native/cpp/system/Timer.cpp +++ b/wpilibc/src/main/native/cpp/system/Timer.cpp @@ -7,7 +7,7 @@ #include #include -#include "wpi/driverstation/DriverStation.hpp" +#include "wpi/driverstation/MatchState.hpp" #include "wpi/system/RobotController.hpp" namespace wpi { @@ -99,5 +99,5 @@ wpi::units::second_t Timer::GetMonotonicTimestamp() { } wpi::units::second_t Timer::GetMatchTime() { - return wpi::DriverStation::GetMatchTime(); + return wpi::MatchState::GetMatchTime(); } diff --git a/wpilibc/src/main/native/cppcs/RobotBase.cpp b/wpilibc/src/main/native/cppcs/RobotBase.cpp index a6dae70227..be8057a952 100644 --- a/wpilibc/src/main/native/cppcs/RobotBase.cpp +++ b/wpilibc/src/main/native/cppcs/RobotBase.cpp @@ -16,7 +16,8 @@ #include #include "wpi/cameraserver/CameraServerShared.hpp" -#include "wpi/driverstation/DriverStation.hpp" +#include "wpi/driverstation/RobotState.hpp" +#include "wpi/driverstation/internal/DriverStationBackend.hpp" #include "wpi/hal/HAL.h" #include "wpi/hal/UsageReporting.hpp" #include "wpi/math/util/MathShared.hpp" @@ -42,7 +43,7 @@ int wpi::RunHALInitialization() { std::puts("FATAL ERROR: HAL could not be initialized"); return -1; } - DriverStation::RefreshData(); + wpi::internal::DriverStationBackend::RefreshData(); HAL_ReportUsage("Language", "C++"); HAL_ReportUsage("WPILibVersion", GetWPILibVersion()); @@ -134,43 +135,43 @@ static void SetupMathShared() { } bool RobotBase::IsEnabled() { - return DriverStation::IsEnabled(); + return RobotState::IsEnabled(); } bool RobotBase::IsDisabled() { - return DriverStation::IsDisabled(); + return RobotState::IsDisabled(); } bool RobotBase::IsAutonomous() { - return DriverStation::IsAutonomous(); + return RobotState::IsAutonomous(); } bool RobotBase::IsAutonomousEnabled() { - return DriverStation::IsAutonomousEnabled(); + return RobotState::IsAutonomousEnabled(); } bool RobotBase::IsTeleop() { - return DriverStation::IsTeleop(); + return RobotState::IsTeleop(); } bool RobotBase::IsTeleopEnabled() { - return DriverStation::IsTeleopEnabled(); + return RobotState::IsTeleopEnabled(); } bool RobotBase::IsTest() { - return DriverStation::IsTest(); + return RobotState::IsTest(); } bool RobotBase::IsTestEnabled() { - return DriverStation::IsTestEnabled(); + return RobotState::IsTestEnabled(); } int64_t RobotBase::GetOpModeId() { - return DriverStation::GetOpModeId(); + return RobotState::GetOpModeId(); } std::string RobotBase::GetOpMode() { - return DriverStation::GetOpMode(); + return RobotState::GetOpMode(); } std::thread::id RobotBase::GetThreadId() { @@ -219,6 +220,6 @@ RobotBase::RobotBase() { SmartDashboard::init(); - // Call DriverStation::RefreshData() to kick things off - DriverStation::RefreshData(); + // Call wpi::internal::DriverStationBackend::RefreshData() to kick things off + wpi::internal::DriverStationBackend::RefreshData(); } diff --git a/wpilibc/src/main/native/include/wpi/driverstation/Alliance.hpp b/wpilibc/src/main/native/include/wpi/driverstation/Alliance.hpp new file mode 100644 index 0000000000..1340261dbf --- /dev/null +++ b/wpilibc/src/main/native/include/wpi/driverstation/Alliance.hpp @@ -0,0 +1,19 @@ +// 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. + +#pragma once + +namespace wpi { + +/** + * The robot alliance that the robot is a part of. + */ +enum class Alliance { + /// Red alliance. + RED, + /// Blue alliance. + BLUE +}; + +} // namespace wpi diff --git a/wpilibc/src/main/native/include/wpi/driverstation/DriverStation.hpp b/wpilibc/src/main/native/include/wpi/driverstation/DriverStation.hpp index 8287df1fc8..fc5cb24a3c 100644 --- a/wpilibc/src/main/native/include/wpi/driverstation/DriverStation.hpp +++ b/wpilibc/src/main/native/include/wpi/driverstation/DriverStation.hpp @@ -4,672 +4,59 @@ #pragma once -#include -#include -#include - -#include "wpi/hal/DriverStation.hpp" -#include "wpi/hal/DriverStationTypes.hpp" -#include "wpi/math/geometry/Rotation2d.hpp" -#include "wpi/units/time.hpp" -#include "wpi/util/Synchronization.h" +#include "wpi/driverstation/internal/DriverStationBackend.hpp" namespace wpi::log { class DataLog; } // namespace wpi::log -namespace wpi::util { -class Color; -} // namespace wpi::util - namespace wpi { -using wpi::hal::RobotMode; - /** - * Provide access to the network communication data to / from the Driver - * Station. + * Provides access to Driver Station functionality. */ class DriverStation final { public: - /** - * The robot alliance that the robot is a part of. - */ - enum class Alliance { - /// Red alliance. - RED, - /// Blue alliance. - BLUE - }; + DriverStation() = delete; /** - * The type of robot match that the robot is part of. - */ - enum class MatchType { - /// None. - NONE, - /// Practice. - PRACTICE, - /// Qualification. - QUALIFICATION, - /// Elimination. - ELIMINATION - }; - - /** - * A controller POV direction. - */ - enum class POVDirection : uint8_t { - /// POV center. - CENTER = HAL_JOYSTICK_POV_CENTERED, - /// POV up. - UP = HAL_JOYSTICK_POV_UP, - /// POV up right. - UP_RIGHT = HAL_JOYSTICK_POV_RIGHT_UP, - /// POV right. - RIGHT = HAL_JOYSTICK_POV_RIGHT, - /// POV down right. - DOWN_RIGHT = HAL_JOYSTICK_POV_RIGHT_DOWN, - /// POV down. - DOWN = HAL_JOYSTICK_POV_DOWN, - /// POV down left. - DOWN_LEFT = HAL_JOYSTICK_POV_LEFT_DOWN, - /// POV left. - LEFT = HAL_JOYSTICK_POV_LEFT, - /// POV up left. - UP_LEFT = HAL_JOYSTICK_POV_LEFT_UP, - }; - - struct TouchpadFinger final { - bool down = false; - float x = 0.0f; - float y = 0.0f; - }; - - /** - * Gets the angle of a POVDirection. + * Starts logging DriverStation data to data log, including joystick data. + * Repeated calls are ignored. * - * @param angle The POVDirection to convert. - * @return The angle clockwise from straight up, or std::nullopt if the - * POVDirection is CENTER. + * @param log data log */ - static constexpr std::optional GetAngle( - POVDirection angle) { - switch (angle) { - case POVDirection::CENTER: - return std::nullopt; - case POVDirection::UP: - return wpi::math::Rotation2d{0_deg}; - case POVDirection::UP_RIGHT: - return wpi::math::Rotation2d{45_deg}; - case POVDirection::RIGHT: - return wpi::math::Rotation2d{90_deg}; - case POVDirection::DOWN_RIGHT: - return wpi::math::Rotation2d{135_deg}; - case POVDirection::DOWN: - return wpi::math::Rotation2d{180_deg}; - case POVDirection::DOWN_LEFT: - return wpi::math::Rotation2d{225_deg}; - case POVDirection::LEFT: - return wpi::math::Rotation2d{270_deg}; - case POVDirection::UP_LEFT: - return wpi::math::Rotation2d{315_deg}; - default: - return std::nullopt; - } + static void StartDataLog(wpi::log::DataLog& log) { + wpi::internal::DriverStationBackend::StartDataLog(log); } - /// Number of Joystick ports. - static constexpr int JOYSTICK_PORTS = 6; - - /** - * The state of one joystick button. Button indexes begin at 0. - * - * @param stick The joystick to read. - * @param button The button index, beginning at 0. - * @return The state of the joystick button. - */ - static bool GetStickButton(int stick, int button); - - /** - * The state of one joystick button, only if available. Button indexes begin - * at 0. - * - * @param stick The joystick to read. - * @param button The button index, beginning at 0. - * @return The state of the joystick button, or empty if unavailable. - */ - static std::optional GetStickButtonIfAvailable(int stick, int button); - - /** - * Whether one joystick button was pressed since the last check. %Button - * indexes begin at 1. - * - * @param stick The joystick to read. - * @param button The button index, beginning at 0. - * @return Whether the joystick button was pressed since the last check. - */ - static bool GetStickButtonPressed(int stick, int button); - - /** - * Whether one joystick button was released since the last check. %Button - * indexes begin at 1. - * - * @param stick The joystick to read. - * @param button The button index, beginning at 0. - * @return Whether the joystick button was released since the last check. - */ - static bool GetStickButtonReleased(int stick, int button); - - /** - * Get the value of the axis on a joystick. - * - * This depends on the mapping of the joystick connected to the specified - * port. - * - * @param stick The joystick to read. - * @param axis The analog axis value to read from the joystick. - * @return The value of the axis on the joystick. - */ - static double GetStickAxis(int stick, int axis); - - /** - * Get the finger data of a touchpad on a joystick, if available. - * - * @param stick The joystick to read. - * @param touchpad The touchpad index to read from the joystick. - * @param finger The finger index to read from the touchpad. - * @return The finger data of the touchpad on the joystick. - */ - static TouchpadFinger GetStickTouchpadFinger(int stick, int touchpad, - int finger); - - /** - * Whether a finger on a touchpad is available. - * - * @param stick The joystick to read. - * @param touchpad The touchpad index to read from the joystick. - * @param finger The finger index to read from the touchpad. - * @return True if the finger data is available. - */ - static bool GetStickTouchpadFingerAvailable(int stick, int touchpad, - int finger); - - /** - * Get the value of the axis on a joystick, if available. - * - * This depends on the mapping of the joystick connected to the specified - * port. - * - * @param stick The joystick to read. - * @param axis The analog axis value to read from the joystick. - * @return The value of the axis on the joystick, or empty if not available. - */ - static std::optional GetStickAxisIfAvailable(int stick, int axis); - - /** - * Get the state of a POV on the joystick. - * - * @return the angle of the POV. - */ - static POVDirection GetStickPOV(int stick, int pov); - - /** - * The state of the buttons on the joystick. - * - * @param stick The joystick to read. - * @return The state of the buttons on the joystick. - */ - static uint64_t GetStickButtons(int stick); - - /** - * Returns the maximum axis index on a given joystick port. - * - * @param stick The joystick port number - * @return The maximum axis index on the indicated joystick - */ - static int GetStickAxesMaximumIndex(int stick); - - /** - * Returns the mask of available axes on a given joystick port. - * - * @param stick The joystick port number - * @return The mask of available axes on the indicated joystick - */ - static int GetStickAxesAvailable(int stick); - - /** - * Returns the maximum POV index on a given joystick port. - * - * @param stick The joystick port number - * @return The maximum POV index on the indicated joystick - */ - static int GetStickPOVsMaximumIndex(int stick); - - /** - * Returns the mask of available POVs on a given joystick port. - * - * @param stick The joystick port number - * @return The mask of available POVs on the indicated joystick - */ - static int GetStickPOVsAvailable(int stick); - - /** - * Returns the maximum button index on a given joystick port. - * - * @param stick The joystick port number - * @return The maximum button index on the indicated joystick - */ - static int GetStickButtonsMaximumIndex(int stick); - - /** - * Returns the mask of available buttons on a given joystick port. - * - * @param stick The joystick port number - * @return The mask of available buttons on the indicated joystick - */ - static uint64_t GetStickButtonsAvailable(int stick); - - /** - * Returns a boolean indicating if the controller is an xbox controller. - * - * @param stick The joystick port number - * @return A boolean that is true if the controller is an xbox controller. - */ - static bool GetJoystickIsGamepad(int stick); - - /** - * Returns the type of joystick at a given port. - * - * This maps to SDL_GamepadType - * - * @param stick The joystick port number - * @return The HID type of joystick at the given port - */ - static int GetJoystickGamepadType(int stick); - - /** - * Returns the number of outputs supported by the joystick at the given - * port. - * - * @param stick The joystick port number - * @return The number of outputs supported by the joystick at the given port - */ - static int GetJoystickSupportedOutputs(int stick); - - /** - * Returns the name of the joystick at the given port. - * - * @param stick The joystick port number - * @return The name of the joystick at the given port - */ - static std::string GetJoystickName(int stick); - - /** - * Returns if a joystick is connected to the Driver Station. - * - * This makes a best effort guess by looking at the reported number of axis, - * buttons, and POVs attached. - * - * @param stick The joystick port number - * @return true if a joystick is connected - */ - static bool IsJoystickConnected(int stick); - - /** - * Check if the DS has enabled the robot. - * - * @return True if the robot is enabled and the DS is connected - */ - static bool IsEnabled() { - hal::ControlWord controlWord = GetControlWord(); - return controlWord.IsEnabled() && controlWord.IsDSAttached(); - } - - /** - * Check if the robot is disabled. - * - * @return True if the robot is explicitly disabled or the DS is not connected - */ - static bool IsDisabled() { return !IsEnabled(); } - - /** - * Check if the robot is e-stopped. - * - * @return True if the robot is e-stopped - */ - static bool IsEStopped() { return GetControlWord().IsEStopped(); } - - /** - * Gets the current robot mode. - * - *

Note that this does not indicate whether the robot is enabled or - * disabled. - * - * @return robot mode - */ - static RobotMode GetRobotMode() { return GetControlWord().GetRobotMode(); } - - /** - * Check if the DS is commanding autonomous mode. - * - * @return True if the robot is being commanded to be in autonomous mode - */ - static bool IsAutonomous() { return GetControlWord().IsAutonomous(); } - - /** - * Check if the DS is commanding autonomous mode and if it has enabled the - * robot. - * - * @return True if the robot is being commanded to be in autonomous mode and - * enabled. - */ - static bool IsAutonomousEnabled() { - return GetControlWord().IsAutonomousEnabled(); - } - - /** - * Check if the DS is commanding teleop mode. - * - * @return True if the robot is being commanded to be in teleop mode - */ - static bool IsTeleop() { return GetControlWord().IsTeleop(); } - - /** - * Check if the DS is commanding teleop mode and if it has enabled the robot. - * - * @return True if the robot is being commanded to be in teleop mode and - * enabled. - */ - static bool IsTeleopEnabled() { return GetControlWord().IsTeleopEnabled(); } - - /** - * Check if the DS is commanding test mode. - * - * @return True if the robot is being commanded to be in test mode - */ - static bool IsTest() { return GetControlWord().IsTest(); } - - /** - * Check if the DS is commanding Test mode and if it has enabled the robot. - * - * @return True if the robot is being commanded to be in Test mode and - * enabled. - */ - static bool IsTestEnabled() { return GetControlWord().IsTestEnabled(); } - - /** - * Adds an operating mode option. It's necessary to call PublishOpModes() to - * make the added modes visible to the driver station. - * - * @param mode robot mode - * @param name name of the operating mode - * @param group group of the operating mode - * @param description description of the operating mode - * @param textColor text color - * @param backgroundColor background color - * @return unique ID used to later identify the operating mode; if a blank - * name is passed, 0 is returned; identical names for the same robot - * mode result in a 0 return value - */ - static int64_t AddOpMode(RobotMode mode, std::string_view name, - std::string_view group, std::string_view description, - const wpi::util::Color& textColor, - const wpi::util::Color& backgroundColor); - - /** - * Adds an operating mode option. It's necessary to call PublishOpModes() to - * make the added modes visible to the driver station. - * - * @param mode robot mode - * @param name name of the operating mode - * @param group group of the operating mode - * @param description description of the operating mode - * @return unique ID used to later identify the operating mode; if a blank - * name is passed, 0 is returned; identical names for the same robot - * mode result in a 0 return value - */ - static int64_t AddOpMode(RobotMode mode, std::string_view name, - std::string_view group = {}, - std::string_view description = {}); - - /** - * Removes an operating mode option. It's necessary to call PublishOpModes() - * to make the removed mode no longer visible to the driver station. - * - * @param mode robot mode - * @param name name of the operating mode - * @return unique ID for the opmode, or 0 if not found - */ - static int64_t RemoveOpMode(RobotMode mode, std::string_view name); - - /** - * Publishes the operating mode options to the driver station. - */ - static void PublishOpModes(); - - /** - * Clears all operating mode options and publishes an empty list to the driver - * station. - */ - static void ClearOpModes(); - - /** - * Sets the program starting flag in the DS. This will also allow - * getOpModeId() and getOpMode() to return values for the selected - * OpMode in the DS application, if the DS is connected by the time this - * method is called. - * - *

Most users will not need to use this method; the TimedRobot and - * OpModeRobot robot framework classes will call it automatically after - * the main robot class is instantiated. - * - *

This is what changes the DS to showing robot code ready. - */ - static void ObserveUserProgramStarting(); - - /** - * Gets the operating mode selected on the driver station. Note this does not - * mean the robot is enabled; use IsEnabled() for that. In a match, this will - * indicate the operating mode selected for auto before the match starts - * (i.e., while the robot is disabled in auto mode); after the auto period - * ends, this will change to reflect the operating mode selected for teleop. - * - * @return the unique ID provided by the AddOpMode() function; may return 0 or - * a unique ID not added, so callers should be prepared to handle that case - */ - static int64_t GetOpModeId(); - - /** - * Gets the operating mode selected on the driver station. Note this does not - * mean the robot is enabled; use IsEnabled() for that. In a match, this will - * indicate the operating mode selected for auto before the match starts - * (i.e., while the robot is disabled in auto mode); after the auto period - * ends, this will change to reflect the operating mode selected for teleop. - * - * @return Operating mode string; may return a string not in the list of - * options, so callers should be prepared to handle that case - */ - static std::string GetOpMode(); - - /** - * Check to see if the selected operating mode is a particular value. Note - * this does not mean the robot is enabled; use IsEnabled() for that. - * - * @param id operating mode unique ID - * @return True if that mode is the current mode - */ - static bool IsOpMode(int64_t id) { return GetOpModeId() == id; } - - /** - * Check to see if the selected operating mode is a particular value. Note - * this does not mean the robot is enabled; use IsEnabled() for that. - * - * @param mode operating mode - * @return True if that mode is the current mode - */ - static bool IsOpMode(std::string_view mode) { return GetOpMode() == mode; } - - /** - * Check if the DS is attached. - * - * @return True if the DS is connected to the robot - */ - static bool IsDSAttached() { return GetControlWord().IsDSAttached(); } - - /** - * Is the driver station attached to a Field Management System? - * - * @return True if the robot is competing on a field being controlled by a - * Field Management System - */ - static bool IsFMSAttached() { return GetControlWord().IsFMSAttached(); } - - /** - * Returns the game specific message provided by the FMS. - * - * If the FMS is not connected, it is set from the game data setting on the - * driver station. - * - * @return A string containing the game specific message. - */ - static std::optional GetGameData(); - - /** - * Returns the name of the competition event provided by the FMS. - * - * @return A string containing the event name - */ - static std::string GetEventName(); - - /** - * Returns the type of match being played provided by the FMS. - * - * @return The match type enum (NONE, PRACTICE, QUALIFICATION, ELIMINATION) - */ - static MatchType GetMatchType(); - - /** - * Returns the match number provided by the FMS. - * - * @return The number of the match - */ - static int GetMatchNumber(); - - /** - * Returns the number of times the current match has been replayed from the - * FMS. - * - * @return The number of replays - */ - static int GetReplayNumber(); - - /** - * Get the current alliance from the FMS. - * - * If the FMS is not connected, it is set from the team alliance setting on - * the driver station. - * - * @return The alliance (red or blue) or an empty optional if the alliance is - * invalid - */ - static std::optional GetAlliance(); - - /** - * Return the driver station location from the FMS. - * - * If the FMS is not connected, it is set from the team alliance setting on - * the driver station. - * - * This could return 1, 2, or 3. - * - * @return The location of the driver station (1-3, 0 for invalid) - */ - static std::optional GetLocation(); - - /** - * Return the approximate match time. The FMS does not send an official match - * time to the robots, but does send an approximate match time. The value will - * count down the time remaining in the current period (auto or teleop). - * Warning: This is not an official time (so it cannot be used to dispute ref - * calls or guarantee that a function will trigger before the match ends). - * - *

When connected to the real field, this number only changes in full - * integer increments, and always counts down. - * - *

When the DS is in practice mode, this number is a floating point number, - * and counts down. - * - *

When the DS is in teleop or autonomous mode, this number returns -1.0. - * - *

Simulation matches DS behavior without an FMS connected. - * - * @return Time remaining in current match period (auto or teleop) in seconds - */ - static wpi::units::second_t GetMatchTime(); - - /** - * Read the battery voltage. - * - * @return The battery voltage in Volts. - */ - static double GetBatteryVoltage(); - - /** - * Get the current control word. - * - * @return control word - */ - static hal::ControlWord GetControlWord() { return hal::GetControlWord(); } - - /** - * Copy data from the DS task for the user. If no new data exists, it will - * just be returned, otherwise the data will be copied from the DS polling - * loop. - */ - static void RefreshData(); - - /** - * Registers the given handle for DS data refresh notifications. - * - * @param handle The event handle. - */ - static void ProvideRefreshedDataEventHandle(WPI_EventHandle handle); - - /** - * Unregisters the given handle from DS data refresh notifications. - * - * @param handle The event handle. - */ - static void RemoveRefreshedDataEventHandle(WPI_EventHandle handle); - - /** - * Allows the user to specify whether they want joystick connection warnings - * to be printed to the console. This setting is ignored when the FMS is - * connected -- warnings will always be on in that scenario. - * - * @param silence Whether warning messages should be silenced. - */ - static void SilenceJoystickConnectionWarning(bool silence); - - /** - * Returns whether joystick connection warnings are silenced. This will - * always return false when connected to the FMS. - * - * @return Whether joystick connection warnings are silenced. - */ - static bool IsJoystickConnectionWarningSilenced(); - /** * Starts logging DriverStation data to data log. Repeated calls are ignored. * * @param log data log * @param logJoysticks if true, log joystick data */ - static void StartDataLog(wpi::log::DataLog& log, bool logJoysticks = true); + static void StartDataLog(wpi::log::DataLog& log, bool logJoysticks) { + wpi::internal::DriverStationBackend::StartDataLog(log, logJoysticks); + } - private: - DriverStation() = default; + /** + * Registers the given handle for DS data refresh notifications. + * + * @param handle The event handle. + */ + static void ProvideRefreshedDataEventHandle(WPI_EventHandle handle) { + wpi::internal::DriverStationBackend::ProvideRefreshedDataEventHandle( + handle); + } + + /** + * Unregisters the given handle from DS data refresh notifications. + * + * @param handle The event handle. + */ + static void RemoveRefreshedDataEventHandle(WPI_EventHandle handle) { + wpi::internal::DriverStationBackend::RemoveRefreshedDataEventHandle(handle); + } }; } // namespace wpi diff --git a/wpilibc/src/main/native/include/wpi/driverstation/GenericHID.hpp b/wpilibc/src/main/native/include/wpi/driverstation/GenericHID.hpp index 5627398fcc..04a4753f14 100644 --- a/wpilibc/src/main/native/include/wpi/driverstation/GenericHID.hpp +++ b/wpilibc/src/main/native/include/wpi/driverstation/GenericHID.hpp @@ -8,7 +8,9 @@ #include -#include "wpi/driverstation/DriverStation.hpp" +#include "wpi/driverstation/POVDirection.hpp" +#include "wpi/driverstation/TouchpadFinger.hpp" +#include "wpi/driverstation/internal/DriverStationBackend.hpp" namespace wpi { @@ -156,7 +158,7 @@ class GenericHID { * @param pov The index of the POV to read (starting at 0) * @return the angle of the POV. */ - DriverStation::POVDirection GetPOV(int pov = 0) const; + POVDirection GetPOV(int pov = 0) const; /** * Constructs a BooleanEvent instance based around this angle of a POV on the @@ -167,7 +169,7 @@ class GenericHID { * @return a BooleanEvent instance based around this angle of a POV on the * HID. */ - BooleanEvent POV(DriverStation::POVDirection angle, EventLoop* loop) const; + BooleanEvent POV(POVDirection angle, EventLoop* loop) const; /** * Constructs a BooleanEvent instance based around this angle of a POV on the @@ -179,8 +181,7 @@ class GenericHID { * @return a BooleanEvent instance based around this angle of a POV on the * HID. */ - BooleanEvent POV(int pov, DriverStation::POVDirection angle, - EventLoop* loop) const; + BooleanEvent POV(int pov, POVDirection angle, EventLoop* loop) const; /** * Constructs a BooleanEvent instance based around the up direction of @@ -385,8 +386,7 @@ class GenericHID { * @param finger The finger to read. * @return The touchpad finger data. */ - DriverStation::TouchpadFinger GetTouchpadFinger(int touchpad, - int finger) const; + TouchpadFinger GetTouchpadFinger(int touchpad, int finger) const; private: int m_port; diff --git a/wpilibc/src/main/native/include/wpi/driverstation/MatchState.hpp b/wpilibc/src/main/native/include/wpi/driverstation/MatchState.hpp new file mode 100644 index 0000000000..10607da09e --- /dev/null +++ b/wpilibc/src/main/native/include/wpi/driverstation/MatchState.hpp @@ -0,0 +1,124 @@ +// 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. + +#pragma once + +#include +#include + +#include "wpi/driverstation/Alliance.hpp" +#include "wpi/driverstation/MatchType.hpp" +#include "wpi/driverstation/internal/DriverStationBackend.hpp" + +namespace wpi { + +/** + * Provides access to match state information from the Driver Station. + */ +class MatchState final { + public: + MatchState() = delete; + + /** + * Return the approximate match time. The FMS does not send an official match + * time to the robots, but does send an approximate match time. The value will + * count down the time remaining in the current period (auto or teleop). + * Warning: This is not an official time (so it cannot be used to dispute ref + * calls or guarantee that a function will trigger before the match ends). + * + * When connected to the real field, this number only changes in full integer + * increments, and always counts down. + * + * When the DS is in practice mode, this number is a floating point number, + * and counts down. + * + * When the DS is in teleop or autonomous mode, this number returns -1.0. + * + * Simulation matches DS behavior without an FMS connected. + * + * @return Time remaining in current match period (auto or teleop) in seconds + */ + static wpi::units::second_t GetMatchTime() { + return wpi::internal::DriverStationBackend::GetMatchTime(); + } + + /** + * Get the current alliance from the FMS. + * + * If the FMS is not connected, it is set from the team alliance setting on + * the driver station. + * + * @return The alliance (red or blue) or an empty optional if the alliance is + * invalid + */ + static std::optional GetAlliance() { + return wpi::internal::DriverStationBackend::GetAlliance(); + } + + /** + * Return the driver station location from the FMS. + * + * If the FMS is not connected, it is set from the team alliance setting on + * the driver station. + * + * This could return 1, 2, or 3. + * + * @return The location of the driver station (1-3, 0 for invalid) + */ + static std::optional GetLocation() { + return wpi::internal::DriverStationBackend::GetLocation(); + } + + /** + * Returns the number of times the current match has been replayed from the + * FMS. + * + * @return The number of replays + */ + static int GetReplayNumber() { + return wpi::internal::DriverStationBackend::GetReplayNumber(); + } + + /** + * Returns the match number provided by the FMS. + * + * @return The number of the match + */ + static int GetMatchNumber() { + return wpi::internal::DriverStationBackend::GetMatchNumber(); + } + + /** + * Returns the type of match being played provided by the FMS. + * + * @return The match type enum (kNone, kPractice, kQualification, + * kElimination) + */ + static MatchType GetMatchType() { + return wpi::internal::DriverStationBackend::GetMatchType(); + } + + /** + * Returns the name of the competition event provided by the FMS. + * + * @return A string containing the event name + */ + static std::string GetEventName() { + return wpi::internal::DriverStationBackend::GetEventName(); + } + + /** + * Returns the game specific message provided by the FMS. + * + * If the FMS is not connected, it is set from the game data setting on the + * driver station. + * + * @return A string containing the game specific message. + */ + static std::optional GetGameData() { + return wpi::internal::DriverStationBackend::GetGameData(); + } +}; + +} // namespace wpi diff --git a/wpilibc/src/main/native/include/wpi/driverstation/MatchType.hpp b/wpilibc/src/main/native/include/wpi/driverstation/MatchType.hpp new file mode 100644 index 0000000000..609ae23414 --- /dev/null +++ b/wpilibc/src/main/native/include/wpi/driverstation/MatchType.hpp @@ -0,0 +1,23 @@ +// 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. + +#pragma once + +namespace wpi { + +/** + * The type of robot match that the robot is part of. + */ +enum class MatchType { + /// None. + NONE, + /// Practice. + PRACTICE, + /// Qualification. + QUALIFICATION, + /// Elimination. + ELIMINATION +}; + +} // namespace wpi diff --git a/wpilibc/src/main/native/include/wpi/driverstation/POVDirection.hpp b/wpilibc/src/main/native/include/wpi/driverstation/POVDirection.hpp new file mode 100644 index 0000000000..dab6c02c72 --- /dev/null +++ b/wpilibc/src/main/native/include/wpi/driverstation/POVDirection.hpp @@ -0,0 +1,72 @@ +// 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. + +#pragma once + +#include +#include + +#include "wpi/hal/DriverStationTypes.h" +#include "wpi/math/geometry/Rotation2d.hpp" + +namespace wpi { + +/** + * A controller POV direction. + */ +enum class POVDirection : uint8_t { + /// POV center. + CENTER = HAL_JOYSTICK_POV_CENTERED, + /// POV up. + UP = HAL_JOYSTICK_POV_UP, + /// POV up right. + UP_RIGHT = HAL_JOYSTICK_POV_RIGHT_UP, + /// POV right. + RIGHT = HAL_JOYSTICK_POV_RIGHT, + /// POV down right. + DOWN_RIGHT = HAL_JOYSTICK_POV_RIGHT_DOWN, + /// POV down. + DOWN = HAL_JOYSTICK_POV_DOWN, + /// POV down left. + DOWN_LEFT = HAL_JOYSTICK_POV_LEFT_DOWN, + /// POV left. + LEFT = HAL_JOYSTICK_POV_LEFT, + /// POV up left. + UP_LEFT = HAL_JOYSTICK_POV_LEFT_UP, +}; + +/** + * Gets the angle of a POVDirection. + * + * @param angle The POVDirection to convert. + * @return The angle clockwise from straight up, or std::nullopt if the + * POVDirection is CENTER. + */ +constexpr std::optional GetPOVAngle(POVDirection angle) { + using enum POVDirection; + switch (angle) { + case CENTER: + return std::nullopt; + case UP: + return wpi::math::Rotation2d{0_deg}; + case UP_RIGHT: + return wpi::math::Rotation2d{45_deg}; + case RIGHT: + return wpi::math::Rotation2d{90_deg}; + case DOWN_RIGHT: + return wpi::math::Rotation2d{135_deg}; + case DOWN: + return wpi::math::Rotation2d{180_deg}; + case DOWN_LEFT: + return wpi::math::Rotation2d{225_deg}; + case LEFT: + return wpi::math::Rotation2d{270_deg}; + case UP_LEFT: + return wpi::math::Rotation2d{315_deg}; + default: + return std::nullopt; + } +} + +} // namespace wpi diff --git a/wpilibc/src/main/native/include/wpi/driverstation/RobotState.hpp b/wpilibc/src/main/native/include/wpi/driverstation/RobotState.hpp new file mode 100644 index 0000000000..d50e13b414 --- /dev/null +++ b/wpilibc/src/main/native/include/wpi/driverstation/RobotState.hpp @@ -0,0 +1,256 @@ +// 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. + +#pragma once + +#include +#include +#include + +#include "wpi/driverstation/internal/DriverStationBackend.hpp" + +namespace wpi { + +using wpi::hal::RobotMode; + +/** + * Provides access to robot state information from the Driver Station. + */ +class RobotState final { + public: + RobotState() = delete; + + /** + * Check if the DS has enabled the robot. + * + * @return True if the robot is enabled and the DS is connected + */ + static bool IsEnabled() { + return wpi::internal::DriverStationBackend::IsEnabled(); + } + + /** + * Check if the robot is disabled. + * + * @return True if the robot is explicitly disabled or the DS is not connected + */ + static bool IsDisabled() { + return wpi::internal::DriverStationBackend::IsDisabled(); + } + + /** + * Check if the robot is e-stopped. + * + * @return True if the robot is e-stopped + */ + static bool IsEStopped() { + return wpi::internal::DriverStationBackend::IsEStopped(); + } + + /** + * Gets the current robot mode. + * + * Note that this does not indicate whether the robot is enabled or disabled. + * + * @return robot mode + */ + static RobotMode GetRobotMode() { + return wpi::internal::DriverStationBackend::GetRobotMode(); + } + + /** + * Check if the DS is commanding autonomous mode. + * + * @return True if the robot is being commanded to be in autonomous mode + */ + static bool IsAutonomous() { + return wpi::internal::DriverStationBackend::IsAutonomous(); + } + + /** + * Check if the DS is commanding autonomous mode and if it has enabled the + * robot. + * + * @return True if the robot is being commanded to be in autonomous mode and + * enabled. + */ + static bool IsAutonomousEnabled() { + return wpi::internal::DriverStationBackend::IsAutonomousEnabled(); + } + + /** + * Check if the DS is commanding teleop mode. + * + * @return True if the robot is being commanded to be in teleop mode + */ + static bool IsTeleop() { + return wpi::internal::DriverStationBackend::IsTeleop(); + } + + /** + * Check if the DS is commanding teleop mode and if it has enabled the robot. + * + * @return True if the robot is being commanded to be in teleop mode and + * enabled. + */ + static bool IsTeleopEnabled() { + return wpi::internal::DriverStationBackend::IsTeleopEnabled(); + } + + /** + * Check if the DS is commanding test mode. + * + * @return True if the robot is being commanded to be in test mode + */ + static bool IsTest() { return wpi::internal::DriverStationBackend::IsTest(); } + + /** + * Check if the DS is commanding Test mode and if it has enabled the robot. + * + * @return True if the robot is being commanded to be in Test mode and + * enabled. + */ + static bool IsTestEnabled() { + return wpi::internal::DriverStationBackend::IsTestEnabled(); + } + + /** + * Adds an operating mode option. It's necessary to call PublishOpModes() to + * make the added modes visible to the driver station. + * + * @param mode robot mode + * @param name name of the operating mode + * @param group group of the operating mode + * @param description description of the operating mode + * @param textColor text color + * @param backgroundColor background color + * @return unique ID used to later identify the operating mode; if a blank + * name is passed, 0 is returned; identical names for the same robot + * mode result in a 0 return value + */ + static int64_t AddOpMode(RobotMode mode, std::string_view name, + std::string_view group, std::string_view description, + const wpi::util::Color& textColor, + const wpi::util::Color& backgroundColor) { + return wpi::internal::DriverStationBackend::AddOpMode( + mode, name, group, description, textColor, backgroundColor); + } + + /** + * Adds an operating mode option. It's necessary to call PublishOpModes() to + * make the added modes visible to the driver station. + * + * @param mode robot mode + * @param name name of the operating mode + * @param group group of the operating mode + * @param description description of the operating mode + * @return unique ID used to later identify the operating mode; if a blank + * name is passed, 0 is returned; identical names for the same robot + * mode result in a 0 return value + */ + static int64_t AddOpMode(RobotMode mode, std::string_view name, + std::string_view group = {}, + std::string_view description = {}) { + return wpi::internal::DriverStationBackend::AddOpMode(mode, name, group, + description); + } + + /** + * Removes an operating mode option. It's necessary to call PublishOpModes() + * to make the removed mode no longer visible to the driver station. + * + * @param mode robot mode + * @param name name of the operating mode + * @return unique ID for the opmode, or 0 if not found + */ + static int64_t RemoveOpMode(RobotMode mode, std::string_view name) { + return wpi::internal::DriverStationBackend::RemoveOpMode(mode, name); + } + + /** + * Publishes the operating mode options to the driver station. + */ + static void PublishOpModes() { + wpi::internal::DriverStationBackend::PublishOpModes(); + } + + /** + * Clears all operating mode options and publishes an empty list to the driver + * station. + */ + static void ClearOpModes() { + wpi::internal::DriverStationBackend::ClearOpModes(); + } + + /** + * Gets the operating mode selected on the driver station. Note this does not + * mean the robot is enabled; use IsEnabled() for that. In a match, this will + * indicate the operating mode selected for auto before the match starts + * (i.e., while the robot is disabled in auto mode); after the auto period + * ends, this will change to reflect the operating mode selected for teleop. + * + * @return the unique ID provided by the AddOpMode() function; may return 0 or + * a unique ID not added, so callers should be prepared to handle that case + */ + static int64_t GetOpModeId() { + return wpi::internal::DriverStationBackend::GetOpModeId(); + } + + /** + * Gets the operating mode selected on the driver station. Note this does not + * mean the robot is enabled; use IsEnabled() for that. In a match, this will + * indicate the operating mode selected for auto before the match starts + * (i.e., while the robot is disabled in auto mode); after the auto period + * ends, this will change to reflect the operating mode selected for teleop. + * + * @return Operating mode string; may return a string not in the list of + * options, so callers should be prepared to handle that case + */ + static std::string GetOpMode() { + return wpi::internal::DriverStationBackend::GetOpMode(); + } + + /** + * Check to see if the selected operating mode is a particular value. Note + * this does not mean the robot is enabled; use IsEnabled() for that. + * + * @param id operating mode unique ID + * @return True if that mode is the current mode + */ + static bool IsOpMode(int64_t id) { + return wpi::internal::DriverStationBackend::IsOpMode(id); + } + + /** + * Check to see if the selected operating mode is a particular value. Note + * this does not mean the robot is enabled; use IsEnabled() for that. + * + * @param mode operating mode + * @return True if that mode is the current mode + */ + static bool IsOpMode(std::string_view mode) { + return wpi::internal::DriverStationBackend::IsOpMode(mode); + } + + /** + * Check if the DS is attached. + * + * @return True if the DS is connected to the robot + */ + static bool IsDSAttached() { + return wpi::internal::DriverStationBackend::IsDSAttached(); + } + + /** + * Is the driver station attached to a Field Management System? + * + * @return True if the robot is competing on a field being controlled by a + * Field Management System + */ + static bool IsFMSAttached() { + return wpi::internal::DriverStationBackend::IsFMSAttached(); + } +}; + +} // namespace wpi diff --git a/wpilibc/src/main/native/include/wpi/driverstation/TouchpadFinger.hpp b/wpilibc/src/main/native/include/wpi/driverstation/TouchpadFinger.hpp new file mode 100644 index 0000000000..c819244471 --- /dev/null +++ b/wpilibc/src/main/native/include/wpi/driverstation/TouchpadFinger.hpp @@ -0,0 +1,21 @@ +// 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. + +#pragma once + +namespace wpi { + +/** + * Touchpad finger data from a joystick. + */ +struct TouchpadFinger final { + /// Whether the finger is touching the touchpad. + bool down = false; + /// The x position of the finger on the touchpad. + float x = 0.0f; + /// The y position of the finger on the touchpad. + float y = 0.0f; +}; + +} // namespace wpi diff --git a/wpilibc/src/main/native/include/wpi/driverstation/internal/DriverStationBackend.hpp b/wpilibc/src/main/native/include/wpi/driverstation/internal/DriverStationBackend.hpp new file mode 100644 index 0000000000..2f44ce0471 --- /dev/null +++ b/wpilibc/src/main/native/include/wpi/driverstation/internal/DriverStationBackend.hpp @@ -0,0 +1,595 @@ +// 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. + +#pragma once + +#include +#include +#include + +#include "wpi/driverstation/Alliance.hpp" +#include "wpi/driverstation/MatchType.hpp" +#include "wpi/driverstation/POVDirection.hpp" +#include "wpi/driverstation/TouchpadFinger.hpp" +#include "wpi/hal/DriverStation.h" +#include "wpi/hal/DriverStation.hpp" +#include "wpi/hal/DriverStationTypes.h" +#include "wpi/hal/DriverStationTypes.hpp" +#include "wpi/math/geometry/Rotation2d.hpp" +#include "wpi/units/time.hpp" +#include "wpi/util/Synchronization.h" + +namespace wpi::log { +class DataLog; +} // namespace wpi::log + +namespace wpi::util { +class Color; +} // namespace wpi::util + +namespace wpi::internal { + +using wpi::hal::RobotMode; + +/** + * Provide access to the network communication data to / from the Driver + * Station. + */ +class DriverStationBackend final { + public: + /// Number of Joystick ports. + static constexpr int JOYSTICK_PORTS = 6; + + /** + * The state of one joystick button. Button indexes begin at 0. + * + * @param stick The joystick to read. + * @param button The button index, beginning at 0. + * @return The state of the joystick button. + */ + static bool GetStickButton(int stick, int button); + + /** + * The state of one joystick button, only if available. Button indexes begin + * at 0. + * + * @param stick The joystick to read. + * @param button The button index, beginning at 0. + * @return The state of the joystick button, or empty if unavailable. + */ + static std::optional GetStickButtonIfAvailable(int stick, int button); + + /** + * Whether one joystick button was pressed since the last check. %Button + * indexes begin at 1. + * + * @param stick The joystick to read. + * @param button The button index, beginning at 0. + * @return Whether the joystick button was pressed since the last check. + */ + static bool GetStickButtonPressed(int stick, int button); + + /** + * Whether one joystick button was released since the last check. %Button + * indexes begin at 1. + * + * @param stick The joystick to read. + * @param button The button index, beginning at 0. + * @return Whether the joystick button was released since the last check. + */ + static bool GetStickButtonReleased(int stick, int button); + + /** + * Get the value of the axis on a joystick. + * + * This depends on the mapping of the joystick connected to the specified + * port. + * + * @param stick The joystick to read. + * @param axis The analog axis value to read from the joystick. + * @return The value of the axis on the joystick. + */ + static double GetStickAxis(int stick, int axis); + + /** + * Get the finger data of a touchpad on a joystick, if available. + * + * @param stick The joystick to read. + * @param touchpad The touchpad index to read from the joystick. + * @param finger The finger index to read from the touchpad. + * @return The finger data of the touchpad on the joystick. + */ + static TouchpadFinger GetStickTouchpadFinger(int stick, int touchpad, + int finger); + + /** + * Whether a finger on a touchpad is available. + * + * @param stick The joystick to read. + * @param touchpad The touchpad index to read from the joystick. + * @param finger The finger index to read from the touchpad. + * @return True if the finger data is available. + */ + static bool GetStickTouchpadFingerAvailable(int stick, int touchpad, + int finger); + + /** + * Get the value of the axis on a joystick, if available. + * + * This depends on the mapping of the joystick connected to the specified + * port. + * + * @param stick The joystick to read. + * @param axis The analog axis value to read from the joystick. + * @return The value of the axis on the joystick, or empty if not available. + */ + static std::optional GetStickAxisIfAvailable(int stick, int axis); + + /** + * Get the state of a POV on the joystick. + * + * @return the angle of the POV. + */ + static POVDirection GetStickPOV(int stick, int pov); + + /** + * The state of the buttons on the joystick. + * + * @param stick The joystick to read. + * @return The state of the buttons on the joystick. + */ + static uint64_t GetStickButtons(int stick); + + /** + * Returns the maximum axis index on a given joystick port. + * + * @param stick The joystick port number + * @return The maximum axis index on the indicated joystick + */ + static int GetStickAxesMaximumIndex(int stick); + + /** + * Returns the mask of available axes on a given joystick port. + * + * @param stick The joystick port number + * @return The mask of available axes on the indicated joystick + */ + static int GetStickAxesAvailable(int stick); + + /** + * Returns the maximum POV index on a given joystick port. + * + * @param stick The joystick port number + * @return The maximum POV index on the indicated joystick + */ + static int GetStickPOVsMaximumIndex(int stick); + + /** + * Returns the mask of available POVs on a given joystick port. + * + * @param stick The joystick port number + * @return The mask of available POVs on the indicated joystick + */ + static int GetStickPOVsAvailable(int stick); + + /** + * Returns the maximum button index on a given joystick port. + * + * @param stick The joystick port number + * @return The maximum button index on the indicated joystick + */ + static int GetStickButtonsMaximumIndex(int stick); + + /** + * Returns the mask of available buttons on a given joystick port. + * + * @param stick The joystick port number + * @return The mask of available buttons on the indicated joystick + */ + static uint64_t GetStickButtonsAvailable(int stick); + + /** + * Returns a boolean indicating if the controller is an xbox controller. + * + * @param stick The joystick port number + * @return A boolean that is true if the controller is an xbox controller. + */ + static bool GetJoystickIsGamepad(int stick); + + /** + * Returns the type of joystick at a given port. + * + * This maps to SDL_GamepadType + * + * @param stick The joystick port number + * @return The HID type of joystick at the given port + */ + static int GetJoystickGamepadType(int stick); + + /** + * Returns the number of outputs supported by the joystick at the given + * port. + * + * @param stick The joystick port number + * @return The number of outputs supported by the joystick at the given port + */ + static int GetJoystickSupportedOutputs(int stick); + + /** + * Returns the name of the joystick at the given port. + * + * @param stick The joystick port number + * @return The name of the joystick at the given port + */ + static std::string GetJoystickName(int stick); + + /** + * Returns if a joystick is connected to the Driver Station. + * + * This makes a best effort guess by looking at the reported number of axis, + * buttons, and POVs attached. + * + * @param stick The joystick port number + * @return true if a joystick is connected + */ + static bool IsJoystickConnected(int stick); + + /** + * Check if the DS has enabled the robot. + * + * @return True if the robot is enabled and the DS is connected + */ + static bool IsEnabled() { + hal::ControlWord controlWord = GetControlWord(); + return controlWord.IsEnabled() && controlWord.IsDSAttached(); + } + + /** + * Check if the robot is disabled. + * + * @return True if the robot is explicitly disabled or the DS is not connected + */ + static bool IsDisabled() { return !IsEnabled(); } + + /** + * Check if the robot is e-stopped. + * + * @return True if the robot is e-stopped + */ + static bool IsEStopped() { return GetControlWord().IsEStopped(); } + + /** + * Gets the current robot mode. + * + *

Note that this does not indicate whether the robot is enabled or + * disabled. + * + * @return robot mode + */ + static RobotMode GetRobotMode() { return GetControlWord().GetRobotMode(); } + + /** + * Check if the DS is commanding autonomous mode. + * + * @return True if the robot is being commanded to be in autonomous mode + */ + static bool IsAutonomous() { return GetControlWord().IsAutonomous(); } + + /** + * Check if the DS is commanding autonomous mode and if it has enabled the + * robot. + * + * @return True if the robot is being commanded to be in autonomous mode and + * enabled. + */ + static bool IsAutonomousEnabled() { + return GetControlWord().IsAutonomousEnabled(); + } + + /** + * Check if the DS is commanding teleop mode. + * + * @return True if the robot is being commanded to be in teleop mode + */ + static bool IsTeleop() { return GetControlWord().IsTeleop(); } + + /** + * Check if the DS is commanding teleop mode and if it has enabled the robot. + * + * @return True if the robot is being commanded to be in teleop mode and + * enabled. + */ + static bool IsTeleopEnabled() { return GetControlWord().IsTeleopEnabled(); } + + /** + * Check if the DS is commanding test mode. + * + * @return True if the robot is being commanded to be in test mode + */ + static bool IsTest() { return GetControlWord().IsTest(); } + + /** + * Check if the DS is commanding Test mode and if it has enabled the robot. + * + * @return True if the robot is being commanded to be in Test mode and + * enabled. + */ + static bool IsTestEnabled() { return GetControlWord().IsTestEnabled(); } + + /** + * Adds an operating mode option. It's necessary to call PublishOpModes() to + * make the added modes visible to the driver station. + * + * @param mode robot mode + * @param name name of the operating mode + * @param group group of the operating mode + * @param description description of the operating mode + * @param textColor text color + * @param backgroundColor background color + * @return unique ID used to later identify the operating mode; if a blank + * name is passed, 0 is returned; identical names for the same robot + * mode result in a 0 return value + */ + static int64_t AddOpMode(RobotMode mode, std::string_view name, + std::string_view group, std::string_view description, + const wpi::util::Color& textColor, + const wpi::util::Color& backgroundColor); + + /** + * Adds an operating mode option. It's necessary to call PublishOpModes() to + * make the added modes visible to the driver station. + * + * @param mode robot mode + * @param name name of the operating mode + * @param group group of the operating mode + * @param description description of the operating mode + * @return unique ID used to later identify the operating mode; if a blank + * name is passed, 0 is returned; identical names for the same robot + * mode result in a 0 return value + */ + static int64_t AddOpMode(RobotMode mode, std::string_view name, + std::string_view group = {}, + std::string_view description = {}); + + /** + * Removes an operating mode option. It's necessary to call PublishOpModes() + * to make the removed mode no longer visible to the driver station. + * + * @param mode robot mode + * @param name name of the operating mode + * @return unique ID for the opmode, or 0 if not found + */ + static int64_t RemoveOpMode(RobotMode mode, std::string_view name); + + /** + * Publishes the operating mode options to the driver station. + */ + static void PublishOpModes(); + + /** + * Clears all operating mode options and publishes an empty list to the driver + * station. + */ + static void ClearOpModes(); + + /** + * Sets the program starting flag in the DS. This will also allow + * getOpModeId() and getOpMode() to return values for the selected + * OpMode in the DS application, if the DS is connected by the time this + * method is called. + * + *

Most users will not need to use this method; the TimedRobot and + * OpModeRobot robot framework classes will call it automatically after + * the main robot class is instantiated. + * + *

This is what changes the DS to showing robot code ready. + */ + static void ObserveUserProgramStarting(); + + /** + * Gets the operating mode selected on the driver station. Note this does not + * mean the robot is enabled; use IsEnabled() for that. In a match, this will + * indicate the operating mode selected for auto before the match starts + * (i.e., while the robot is disabled in auto mode); after the auto period + * ends, this will change to reflect the operating mode selected for teleop. + * + * @return the unique ID provided by the AddOpMode() function; may return 0 or + * a unique ID not added, so callers should be prepared to handle that case + */ + static int64_t GetOpModeId(); + + /** + * Gets the operating mode selected on the driver station. Note this does not + * mean the robot is enabled; use IsEnabled() for that. In a match, this will + * indicate the operating mode selected for auto before the match starts + * (i.e., while the robot is disabled in auto mode); after the auto period + * ends, this will change to reflect the operating mode selected for teleop. + * + * @return Operating mode string; may return a string not in the list of + * options, so callers should be prepared to handle that case + */ + static std::string GetOpMode(); + + /** + * Check to see if the selected operating mode is a particular value. Note + * this does not mean the robot is enabled; use IsEnabled() for that. + * + * @param id operating mode unique ID + * @return True if that mode is the current mode + */ + static bool IsOpMode(int64_t id) { return GetOpModeId() == id; } + + /** + * Check to see if the selected operating mode is a particular value. Note + * this does not mean the robot is enabled; use IsEnabled() for that. + * + * @param mode operating mode + * @return True if that mode is the current mode + */ + static bool IsOpMode(std::string_view mode) { return GetOpMode() == mode; } + + /** + * Check if the DS is attached. + * + * @return True if the DS is connected to the robot + */ + static bool IsDSAttached() { return GetControlWord().IsDSAttached(); } + + /** + * Is the driver station attached to a Field Management System? + * + * @return True if the robot is competing on a field being controlled by a + * Field Management System + */ + static bool IsFMSAttached() { return GetControlWord().IsFMSAttached(); } + + /** + * Returns the game specific message provided by the FMS. + * + * If the FMS is not connected, it is set from the game data setting on the + * driver station. + * + * @return A string containing the game specific message. + */ + static std::optional GetGameData(); + + /** + * Returns the name of the competition event provided by the FMS. + * + * @return A string containing the event name + */ + static std::string GetEventName(); + + /** + * Returns the type of match being played provided by the FMS. + * + * @return The match type enum (kNone, kPractice, kQualification, + * kElimination) + */ + static MatchType GetMatchType(); + + /** + * Returns the match number provided by the FMS. + * + * @return The number of the match + */ + static int GetMatchNumber(); + + /** + * Returns the number of times the current match has been replayed from the + * FMS. + * + * @return The number of replays + */ + static int GetReplayNumber(); + + /** + * Get the current alliance from the FMS. + * + * If the FMS is not connected, it is set from the team alliance setting on + * the driver station. + * + * @return The alliance (red or blue) or an empty optional if the alliance is + * invalid + */ + static std::optional GetAlliance(); + + /** + * Return the driver station location from the FMS. + * + * If the FMS is not connected, it is set from the team alliance setting on + * the driver station. + * + * This could return 1, 2, or 3. + * + * @return The location of the driver station (1-3, 0 for invalid) + */ + static std::optional GetLocation(); + + /** + * Return the approximate match time. The FMS does not send an official match + * time to the robots, but does send an approximate match time. The value will + * count down the time remaining in the current period (auto or teleop). + * Warning: This is not an official time (so it cannot be used to dispute ref + * calls or guarantee that a function will trigger before the match ends). + * + *

When connected to the real field, this number only changes in full + * integer increments, and always counts down. + * + *

When the DS is in practice mode, this number is a floating point number, + * and counts down. + * + *

When the DS is in teleop or autonomous mode, this number returns -1.0. + * + *

Simulation matches DS behavior without an FMS connected. + * + * @return Time remaining in current match period (auto or teleop) in seconds + */ + static wpi::units::second_t GetMatchTime(); + + /** + * Read the battery voltage. + * + * @return The battery voltage in Volts. + */ + static double GetBatteryVoltage(); + + /** + * Get the current control word. + * + * @return control word + */ + static hal::ControlWord GetControlWord() { return hal::GetControlWord(); } + + /** + * Copy data from the DS task for the user. If no new data exists, it will + * just be returned, otherwise the data will be copied from the DS polling + * loop. + */ + static void RefreshData(); + + /** + * Registers the given handle for DS data refresh notifications. + * + * @param handle The event handle. + */ + static void ProvideRefreshedDataEventHandle(WPI_EventHandle handle); + + /** + * Unregisters the given handle from DS data refresh notifications. + * + * @param handle The event handle. + */ + static void RemoveRefreshedDataEventHandle(WPI_EventHandle handle); + + /** + * Allows the user to specify whether they want joystick connection warnings + * to be printed to the console. This setting is ignored when the FMS is + * connected -- warnings will always be on in that scenario. + * + * @param silence Whether warning messages should be silenced. + */ + static void SilenceJoystickConnectionWarning(bool silence); + + /** + * Returns whether joystick connection warnings are silenced. This will + * always return false when connected to the FMS. + * + * @return Whether joystick connection warnings are silenced. + */ + static bool IsJoystickConnectionWarningSilenced(); + + /** + * Starts logging DriverStation data to data log. Repeated calls are ignored. + * + * @param log data log + * @param logJoysticks if true, log joystick data + */ + static void StartDataLog(wpi::log::DataLog& log, bool logJoysticks = true); + + private: + DriverStationBackend() = default; +}; + +} // namespace wpi::internal diff --git a/wpilibc/src/main/native/include/wpi/framework/RobotBase.hpp b/wpilibc/src/main/native/include/wpi/framework/RobotBase.hpp index b7f39ecb82..767f2cd98d 100644 --- a/wpilibc/src/main/native/include/wpi/framework/RobotBase.hpp +++ b/wpilibc/src/main/native/include/wpi/framework/RobotBase.hpp @@ -210,7 +210,7 @@ class RobotBase { * Gets the currently selected operating mode of the driver station. Note this * does not mean the robot is enabled; use IsEnabled() for that. * - * @return the unique ID provided by the DriverStation::AddOpMode() function; + * @return the unique ID provided by the RobotState::AddOpMode() function; * may return 0 or a unique ID not added, so callers should be prepared to * handle that case */ diff --git a/wpilibc/src/main/native/include/wpi/simulation/DriverStationSim.hpp b/wpilibc/src/main/native/include/wpi/simulation/DriverStationSim.hpp index fd1753af0d..2dfaf06fde 100644 --- a/wpilibc/src/main/native/include/wpi/simulation/DriverStationSim.hpp +++ b/wpilibc/src/main/native/include/wpi/simulation/DriverStationSim.hpp @@ -8,7 +8,7 @@ #include -#include "wpi/driverstation/DriverStation.hpp" +#include "wpi/driverstation/internal/DriverStationBackend.hpp" #include "wpi/hal/DriverStationTypes.h" #include "wpi/hal/simulation/DriverStationData.h" #include "wpi/simulation/CallbackStore.hpp" @@ -281,14 +281,15 @@ class DriverStationSim { static void NotifyNewData(); /** - * Sets suppression of DriverStation::ReportError and ReportWarning messages. + * Sets suppression of DriverStationErrors::ReportError and ReportWarning + * messages. * * @param shouldSend If false then messages will be suppressed. */ static void SetSendError(bool shouldSend); /** - * Sets suppression of DriverStation::SendConsoleLine messages. + * Sets suppression of DriverStationErrors::SendConsoleLine messages. * * @param shouldSend If false then messages will be suppressed. */ @@ -337,8 +338,7 @@ class DriverStationSim { * @param pov The POV number * @param value the angle of the POV */ - static void SetJoystickPOV(int stick, int pov, - DriverStation::POVDirection value); + static void SetJoystickPOV(int stick, int pov, POVDirection value); /** * Sets the number of axes for a joystick. @@ -433,7 +433,7 @@ class DriverStationSim { * * @param type the match type */ - static void SetMatchType(DriverStation::MatchType type); + static void SetMatchType(MatchType type); /** * Sets the match number. diff --git a/wpilibc/src/main/native/include/wpi/simulation/GenericHIDSim.hpp b/wpilibc/src/main/native/include/wpi/simulation/GenericHIDSim.hpp index 955238493b..be8815ff15 100644 --- a/wpilibc/src/main/native/include/wpi/simulation/GenericHIDSim.hpp +++ b/wpilibc/src/main/native/include/wpi/simulation/GenericHIDSim.hpp @@ -6,8 +6,8 @@ #include -#include "wpi/driverstation/DriverStation.hpp" #include "wpi/driverstation/GenericHID.hpp" +#include "wpi/driverstation/internal/DriverStationBackend.hpp" namespace wpi { @@ -61,14 +61,14 @@ class GenericHIDSim { * @param pov the POV to set * @param value the new value */ - void SetPOV(int pov, DriverStation::POVDirection value); + void SetPOV(int pov, POVDirection value); /** * Set the value of the default POV (port 0). * * @param value the new value */ - void SetPOV(DriverStation::POVDirection value); + void SetPOV(POVDirection value); void SetAxesMaximumIndex(int maximumIndex); diff --git a/wpilibc/src/main/python/pyproject.toml b/wpilibc/src/main/python/pyproject.toml index c25ac12bf3..73c81e69d6 100644 --- a/wpilibc/src/main/python/pyproject.toml +++ b/wpilibc/src/main/python/pyproject.toml @@ -105,8 +105,15 @@ MecanumDrive = "wpi/drive/MecanumDrive.hpp" RobotDriveBase = "wpi/drive/RobotDriveBase.hpp" # wpi/driverstation +DriverStationBackend = "wpi/driverstation/internal/DriverStationBackend.hpp" +Alliance = "wpi/driverstation/Alliance.hpp" Alert = "wpi/driverstation/Alert.hpp" DriverStation = "wpi/driverstation/DriverStation.hpp" +MatchState = "wpi/driverstation/MatchState.hpp" +MatchType = "wpi/driverstation/MatchType.hpp" +POVDirection = "wpi/driverstation/POVDirection.hpp" +RobotState = "wpi/driverstation/RobotState.hpp" +TouchpadFinger = "wpi/driverstation/TouchpadFinger.hpp" Gamepad = "wpi/driverstation/Gamepad.hpp" GenericHID = "wpi/driverstation/GenericHID.hpp" Joystick = "wpi/driverstation/Joystick.hpp" diff --git a/wpilibc/src/main/python/semiwrap/Alliance.yml b/wpilibc/src/main/python/semiwrap/Alliance.yml new file mode 100644 index 0000000000..30148c0787 --- /dev/null +++ b/wpilibc/src/main/python/semiwrap/Alliance.yml @@ -0,0 +1,2 @@ +enums: + Alliance: diff --git a/wpilibc/src/main/python/semiwrap/DriverStation.yml b/wpilibc/src/main/python/semiwrap/DriverStation.yml index 02dd5ed365..121801321a 100644 --- a/wpilibc/src/main/python/semiwrap/DriverStation.yml +++ b/wpilibc/src/main/python/semiwrap/DriverStation.yml @@ -1,82 +1,12 @@ extra_includes: - wpi/datalog/DataLog.hpp -- wpi/util/Color.hpp classes: wpi::DriverStation: - attributes: - JOYSTICK_PORTS: - enums: - Alliance: - MatchType: - POVDirection: methods: - GetStickButton: - GetStickButtonPressed: - GetStickButtonReleased: - GetStickAxis: - GetStickPOV: - GetStickButtons: - GetJoystickGamepadType: - GetJoystickSupportedOutputs: - GetJoystickName: - IsJoystickConnected: - IsEnabled: - IsDisabled: - IsEStopped: - IsAutonomous: - IsAutonomousEnabled: - IsTeleop: - IsTeleopEnabled: - IsTest: - IsTestEnabled: - IsDSAttached: - IsFMSAttached: - GetGameData: - GetEventName: - GetMatchType: - GetMatchNumber: - GetReplayNumber: - GetAlliance: - GetLocation: - GetMatchTime: - GetBatteryVoltage: - RefreshData: ProvideRefreshedDataEventHandle: RemoveRefreshedDataEventHandle: - SilenceJoystickConnectionWarning: - IsJoystickConnectionWarningSilenced: StartDataLog: - GetAngle: - GetJoystickIsGamepad: - GetStickButtonIfAvailable: - GetStickAxisIfAvailable: - GetStickAxesMaximumIndex: - GetStickAxesAvailable: - GetStickPOVsMaximumIndex: - GetStickPOVsAvailable: - GetStickButtonsMaximumIndex: - GetStickButtonsAvailable: - GetRobotMode: - AddOpMode: overloads: - RobotMode, std::string_view, std::string_view, std::string_view: - RobotMode, std::string_view, std::string_view, std::string_view, const wpi::util::Color&, const wpi::util::Color&: - RemoveOpMode: - PublishOpModes: - ClearOpModes: - GetOpModeId: - GetOpMode: - IsOpMode: - overloads: - int64_t: - std::string_view: - GetControlWord: - GetStickTouchpadFinger: - GetStickTouchpadFingerAvailable: - ObserveUserProgramStarting: - wpi::DriverStation::TouchpadFinger: - attributes: - down: - x: - y: + wpi::log::DataLog&: + wpi::log::DataLog&, bool: diff --git a/wpilibc/src/main/python/semiwrap/DriverStationBackend.yml b/wpilibc/src/main/python/semiwrap/DriverStationBackend.yml new file mode 100644 index 0000000000..246adacdad --- /dev/null +++ b/wpilibc/src/main/python/semiwrap/DriverStationBackend.yml @@ -0,0 +1,72 @@ +extra_includes: +- wpi/datalog/DataLog.hpp +- wpi/util/Color.hpp + +classes: + wpi::internal::DriverStationBackend: + attributes: + JOYSTICK_PORTS: + methods: + GetStickButton: + GetStickButtonIfAvailable: + GetStickButtonPressed: + GetStickButtonReleased: + GetStickAxis: + GetStickTouchpadFinger: + GetStickTouchpadFingerAvailable: + GetStickAxisIfAvailable: + GetStickPOV: + GetStickButtons: + GetStickAxesMaximumIndex: + GetStickAxesAvailable: + GetStickPOVsMaximumIndex: + GetStickPOVsAvailable: + GetStickButtonsMaximumIndex: + GetStickButtonsAvailable: + GetJoystickIsGamepad: + GetJoystickGamepadType: + GetJoystickSupportedOutputs: + GetJoystickName: + IsJoystickConnected: + IsEnabled: + IsDisabled: + IsEStopped: + GetRobotMode: + IsAutonomous: + IsAutonomousEnabled: + IsTeleop: + IsTeleopEnabled: + IsTest: + IsTestEnabled: + AddOpMode: + overloads: + RobotMode, std::string_view, std::string_view, std::string_view, const wpi::util::Color&, const wpi::util::Color&: + RobotMode, std::string_view, std::string_view, std::string_view: + RemoveOpMode: + PublishOpModes: + ClearOpModes: + GetOpModeId: + GetOpMode: + IsOpMode: + overloads: + int64_t: + std::string_view: + IsDSAttached: + IsFMSAttached: + GetGameData: + GetEventName: + GetMatchType: + GetMatchNumber: + GetReplayNumber: + GetAlliance: + GetLocation: + GetMatchTime: + GetBatteryVoltage: + GetControlWord: + RefreshData: + ProvideRefreshedDataEventHandle: + RemoveRefreshedDataEventHandle: + SilenceJoystickConnectionWarning: + IsJoystickConnectionWarningSilenced: + StartDataLog: + ObserveUserProgramStarting: diff --git a/wpilibc/src/main/python/semiwrap/GenericHID.yml b/wpilibc/src/main/python/semiwrap/GenericHID.yml index 15b90932fb..9403815764 100644 --- a/wpilibc/src/main/python/semiwrap/GenericHID.yml +++ b/wpilibc/src/main/python/semiwrap/GenericHID.yml @@ -1,5 +1,5 @@ extra_includes: -- wpi/driverstation/DriverStation.hpp +- wpi/driverstation/internal/DriverStationBackend.hpp - wpi/event/BooleanEvent.hpp classes: @@ -19,8 +19,8 @@ classes: GetPOV: POV: overloads: - DriverStation::POVDirection, EventLoop* [const]: - int, DriverStation::POVDirection, EventLoop* [const]: + POVDirection, EventLoop* [const]: + int, POVDirection, EventLoop* [const]: POVUp: POVUpRight: POVRight: diff --git a/wpilibc/src/main/python/semiwrap/Joystick.yml b/wpilibc/src/main/python/semiwrap/Joystick.yml index 70c9921276..019a545dfb 100644 --- a/wpilibc/src/main/python/semiwrap/Joystick.yml +++ b/wpilibc/src/main/python/semiwrap/Joystick.yml @@ -1,5 +1,5 @@ extra_includes: -- wpi/driverstation/DriverStation.hpp +- wpi/driverstation/internal/DriverStationBackend.hpp classes: wpi::Joystick: diff --git a/wpilibc/src/main/python/semiwrap/MatchState.yml b/wpilibc/src/main/python/semiwrap/MatchState.yml new file mode 100644 index 0000000000..ab685b4811 --- /dev/null +++ b/wpilibc/src/main/python/semiwrap/MatchState.yml @@ -0,0 +1,11 @@ +classes: + wpi::MatchState: + methods: + GetMatchTime: + GetAlliance: + GetLocation: + GetReplayNumber: + GetMatchNumber: + GetMatchType: + GetEventName: + GetGameData: diff --git a/wpilibc/src/main/python/semiwrap/MatchType.yml b/wpilibc/src/main/python/semiwrap/MatchType.yml new file mode 100644 index 0000000000..223031a24b --- /dev/null +++ b/wpilibc/src/main/python/semiwrap/MatchType.yml @@ -0,0 +1,2 @@ +enums: + MatchType: diff --git a/wpilibc/src/main/python/semiwrap/NiDsXboxController.yml b/wpilibc/src/main/python/semiwrap/NiDsXboxController.yml index d1768505e7..7c5666a80a 100644 --- a/wpilibc/src/main/python/semiwrap/NiDsXboxController.yml +++ b/wpilibc/src/main/python/semiwrap/NiDsXboxController.yml @@ -1,6 +1,6 @@ extra_includes: - wpi/util/sendable/SendableBuilder.hpp -- wpi/driverstation/DriverStation.hpp +- wpi/driverstation/internal/DriverStationBackend.hpp - wpi/event/BooleanEvent.hpp classes: diff --git a/wpilibc/src/main/python/semiwrap/POVDirection.yml b/wpilibc/src/main/python/semiwrap/POVDirection.yml new file mode 100644 index 0000000000..9bc70eb738 --- /dev/null +++ b/wpilibc/src/main/python/semiwrap/POVDirection.yml @@ -0,0 +1,4 @@ +enums: + POVDirection: +functions: + GetPOVAngle: diff --git a/wpilibc/src/main/python/semiwrap/RobotBase.yml b/wpilibc/src/main/python/semiwrap/RobotBase.yml index a64747063a..95ca956b99 100644 --- a/wpilibc/src/main/python/semiwrap/RobotBase.yml +++ b/wpilibc/src/main/python/semiwrap/RobotBase.yml @@ -1,5 +1,5 @@ extra_includes: -- wpi/driverstation/DriverStation.hpp +- wpi/driverstation/internal/DriverStationBackend.hpp functions: # TODO diff --git a/wpilibc/src/main/python/semiwrap/RobotState.yml b/wpilibc/src/main/python/semiwrap/RobotState.yml new file mode 100644 index 0000000000..3c07a64f28 --- /dev/null +++ b/wpilibc/src/main/python/semiwrap/RobotState.yml @@ -0,0 +1,31 @@ +extra_includes: +- wpi/util/Color.hpp + +classes: + wpi::RobotState: + methods: + IsEnabled: + IsDisabled: + IsEStopped: + GetRobotMode: + IsAutonomous: + IsAutonomousEnabled: + IsTeleop: + IsTeleopEnabled: + IsTest: + IsTestEnabled: + AddOpMode: + overloads: + RobotMode, std::string_view, std::string_view, std::string_view, const wpi::util::Color&, const wpi::util::Color&: + RobotMode, std::string_view, std::string_view, std::string_view: + RemoveOpMode: + PublishOpModes: + ClearOpModes: + GetOpModeId: + GetOpMode: + IsOpMode: + overloads: + int64_t: + std::string_view: + IsDSAttached: + IsFMSAttached: diff --git a/wpilibc/src/main/python/semiwrap/TouchpadFinger.yml b/wpilibc/src/main/python/semiwrap/TouchpadFinger.yml new file mode 100644 index 0000000000..17c0888807 --- /dev/null +++ b/wpilibc/src/main/python/semiwrap/TouchpadFinger.yml @@ -0,0 +1,6 @@ +classes: + wpi::TouchpadFinger: + attributes: + down: + x: + y: diff --git a/wpilibc/src/main/python/semiwrap/simulation/GenericHIDSim.yml b/wpilibc/src/main/python/semiwrap/simulation/GenericHIDSim.yml index 062d7e78d4..5e2f1df4e5 100644 --- a/wpilibc/src/main/python/semiwrap/simulation/GenericHIDSim.yml +++ b/wpilibc/src/main/python/semiwrap/simulation/GenericHIDSim.yml @@ -10,8 +10,8 @@ classes: SetRawAxis: SetPOV: overloads: - int, DriverStation::POVDirection: - DriverStation::POVDirection: + int, POVDirection: + POVDirection: SetGamepadType: SetSupportedOutputs: SetName: diff --git a/wpilibc/src/main/python/wpilib/__init__.py b/wpilibc/src/main/python/wpilib/__init__.py index 170fa05c2e..755f2b8f66 100644 --- a/wpilibc/src/main/python/wpilib/__init__.py +++ b/wpilibc/src/main/python/wpilib/__init__.py @@ -21,6 +21,7 @@ from ._wpilib import ( DigitalOutput, DoubleSolenoid, DriverStation, + DriverStationBackend, DutyCycle, DutyCycleEncoder, EdgeConfiguration, @@ -39,6 +40,7 @@ from ._wpilib import ( Joystick, Koors40, LEDPattern, + MatchState, MecanumDrive, Mechanism2d, MechanismLigament2d, @@ -72,6 +74,7 @@ from ._wpilib import ( RobotBase, RobotController, RobotDriveBase, + RobotState, RuntimeType, SendableBuilderImpl, SendableChooser, @@ -124,6 +127,7 @@ __all__ = [ "DigitalOutput", "DoubleSolenoid", "DriverStation", + "DriverStationBackend", "DutyCycle", "DutyCycleEncoder", "EdgeConfiguration", @@ -142,6 +146,7 @@ __all__ = [ "Joystick", "Koors40", "LEDPattern", + "MatchState", "MecanumDrive", "Mechanism2d", "MechanismLigament2d", @@ -173,6 +178,7 @@ __all__ = [ "PowerDistribution", "Preferences", "RobotBase", + "RobotState", "RobotController", "RobotDriveBase", "RuntimeType", diff --git a/wpilibc/src/main/python/wpilib/_impl/start.py b/wpilibc/src/main/python/wpilib/_impl/start.py index eba991c0c3..ae0053e287 100644 --- a/wpilibc/src/main/python/wpilib/_impl/start.py +++ b/wpilibc/src/main/python/wpilib/_impl/start.py @@ -189,8 +189,8 @@ class RobotStarter: wpilib.SmartDashboard.init() - # Call DriverStation.refreshData() to kick things off - wpilib.DriverStation.refreshData() + # Call DriverStationBackend.refreshData() to kick things off + wpilib.DriverStationBackend.refreshData() try: self.robot = robot_cls() diff --git a/wpilibc/src/main/python/wpilib/testing/pytest_plugin.py b/wpilibc/src/main/python/wpilib/testing/pytest_plugin.py index 26863934ad..0c4d31deae 100644 --- a/wpilibc/src/main/python/wpilib/testing/pytest_plugin.py +++ b/wpilibc/src/main/python/wpilib/testing/pytest_plugin.py @@ -73,7 +73,7 @@ class RobotTestingPlugin: pauseTiming() restartTiming() - wpilib.DriverStation.silenceJoystickConnectionWarning(True) + wpilib.DriverStationBackend.silenceJoystickConnectionWarning(True) DriverStationSim.setRobotMode(RobotMode.AUTONOMOUS) DriverStationSim.setEnabled(False) DriverStationSim.notifyNewData() diff --git a/wpilibc/src/test/native/cpp/DriverStationTest.cpp b/wpilibc/src/test/native/cpp/DriverStationTest.cpp index ee1e298e82..c98849f312 100644 --- a/wpilibc/src/test/native/cpp/DriverStationTest.cpp +++ b/wpilibc/src/test/native/cpp/DriverStationTest.cpp @@ -2,14 +2,13 @@ // 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. -#include "wpi/driverstation/DriverStation.hpp" - #include #include #include #include "wpi/driverstation/Joystick.hpp" +#include "wpi/driverstation/internal/DriverStationBackend.hpp" #include "wpi/simulation/DriverStationSim.hpp" #include "wpi/simulation/SimHooks.hpp" @@ -26,7 +25,7 @@ TEST_P(IsJoystickConnectedParametersTest, IsJoystickConnected) { wpi::sim::DriverStationSim::NotifyNewData(); ASSERT_EQ(std::get<3>(GetParam()), - wpi::DriverStation::IsJoystickConnected(1)); + wpi::internal::DriverStationBackend::IsJoystickConnected(1)); } INSTANTIATE_TEST_SUITE_P(IsConnectedTests, IsJoystickConnectedParametersTest, @@ -47,14 +46,16 @@ TEST_P(JoystickConnectionWarningTest, JoystickConnectionWarnings) { // Set FMS and Silence settings wpi::sim::DriverStationSim::SetFmsAttached(std::get<0>(GetParam())); wpi::sim::DriverStationSim::NotifyNewData(); - wpi::DriverStation::SilenceJoystickConnectionWarning(std::get<1>(GetParam())); + wpi::internal::DriverStationBackend::SilenceJoystickConnectionWarning( + std::get<1>(GetParam())); // Create joystick and attempt to retrieve button. wpi::Joystick joystick(0); joystick.GetRawButton(1); wpi::sim::StepTiming(1_s); - EXPECT_EQ(wpi::DriverStation::IsJoystickConnectionWarningSilenced(), + EXPECT_EQ(wpi::internal::DriverStationBackend:: + IsJoystickConnectionWarningSilenced(), std::get<2>(GetParam())); EXPECT_EQ(::testing::internal::GetCapturedStderr().substr( 0, std::get<3>(GetParam()).size()), diff --git a/wpilibc/src/test/native/cpp/simulation/DriverStationSimTest.cpp b/wpilibc/src/test/native/cpp/simulation/DriverStationSimTest.cpp index 504e33f53f..5cf7b892ce 100644 --- a/wpilibc/src/test/native/cpp/simulation/DriverStationSimTest.cpp +++ b/wpilibc/src/test/native/cpp/simulation/DriverStationSimTest.cpp @@ -7,7 +7,9 @@ #include #include "callback_helpers/TestCallbackHelpers.hpp" -#include "wpi/driverstation/DriverStation.hpp" +#include "wpi/driverstation/MatchState.hpp" +#include "wpi/driverstation/RobotState.hpp" +#include "wpi/driverstation/internal/DriverStationBackend.hpp" #include "wpi/hal/DriverStationTypes.h" #include "wpi/hal/HAL.h" @@ -18,7 +20,7 @@ TEST(DriverStationTest, Enabled) { HAL_Initialize(500, 0); DriverStationSim::ResetData(); - EXPECT_FALSE(DriverStation::IsEnabled()); + EXPECT_FALSE(RobotState::IsEnabled()); BooleanCallback callback; auto cb = DriverStationSim::RegisterEnabledCallback(callback.GetCallback(), false); @@ -26,7 +28,7 @@ TEST(DriverStationTest, Enabled) { DriverStationSim::SetEnabled(true); DriverStationSim::NotifyNewData(); EXPECT_TRUE(DriverStationSim::GetEnabled()); - EXPECT_TRUE(DriverStation::IsEnabled()); + EXPECT_TRUE(RobotState::IsEnabled()); EXPECT_TRUE(callback.WasTriggered()); EXPECT_TRUE(callback.GetLastValue()); } @@ -35,15 +37,15 @@ TEST(DriverStationTest, AutonomousMode) { HAL_Initialize(500, 0); DriverStationSim::ResetData(); - EXPECT_FALSE(DriverStation::IsAutonomous()); + EXPECT_FALSE(RobotState::IsAutonomous()); EnumCallback callback; auto cb = DriverStationSim::RegisterRobotModeCallback(callback.GetCallback(), false); DriverStationSim::SetRobotMode(HAL_ROBOT_MODE_AUTONOMOUS); DriverStationSim::NotifyNewData(); EXPECT_EQ(DriverStationSim::GetRobotMode(), HAL_ROBOT_MODE_AUTONOMOUS); - EXPECT_TRUE(DriverStation::IsAutonomous()); - EXPECT_EQ(DriverStation::GetRobotMode(), RobotMode::AUTONOMOUS); + EXPECT_TRUE(RobotState::IsAutonomous()); + EXPECT_EQ(RobotState::GetRobotMode(), RobotMode::AUTONOMOUS); EXPECT_TRUE(callback.WasTriggered()); EXPECT_EQ(callback.GetLastValue(), HAL_ROBOT_MODE_AUTONOMOUS); } @@ -52,15 +54,15 @@ TEST(DriverStationTest, Mode) { HAL_Initialize(500, 0); DriverStationSim::ResetData(); - EXPECT_FALSE(DriverStation::IsTest()); + EXPECT_FALSE(RobotState::IsTest()); EnumCallback callback; auto cb = DriverStationSim::RegisterRobotModeCallback(callback.GetCallback(), false); DriverStationSim::SetRobotMode(HAL_ROBOT_MODE_TEST); DriverStationSim::NotifyNewData(); EXPECT_EQ(DriverStationSim::GetRobotMode(), HAL_ROBOT_MODE_TEST); - EXPECT_TRUE(DriverStation::IsTest()); - EXPECT_EQ(DriverStation::GetRobotMode(), RobotMode::TEST); + EXPECT_TRUE(RobotState::IsTest()); + EXPECT_EQ(RobotState::GetRobotMode(), RobotMode::TEST); EXPECT_TRUE(callback.WasTriggered()); EXPECT_EQ(callback.GetLastValue(), HAL_ROBOT_MODE_TEST); } @@ -69,14 +71,14 @@ TEST(DriverStationTest, Estop) { HAL_Initialize(500, 0); DriverStationSim::ResetData(); - EXPECT_FALSE(DriverStation::IsEStopped()); + EXPECT_FALSE(RobotState::IsEStopped()); BooleanCallback callback; auto cb = DriverStationSim::RegisterEStopCallback(callback.GetCallback(), false); DriverStationSim::SetEStop(true); DriverStationSim::NotifyNewData(); EXPECT_TRUE(DriverStationSim::GetEStop()); - EXPECT_TRUE(DriverStation::IsEStopped()); + EXPECT_TRUE(RobotState::IsEStopped()); EXPECT_TRUE(callback.WasTriggered()); EXPECT_TRUE(callback.GetLastValue()); } @@ -85,14 +87,14 @@ TEST(DriverStationTest, FmsAttached) { HAL_Initialize(500, 0); DriverStationSim::ResetData(); - EXPECT_FALSE(DriverStation::IsFMSAttached()); + EXPECT_FALSE(RobotState::IsFMSAttached()); BooleanCallback callback; auto cb = DriverStationSim::RegisterFmsAttachedCallback( callback.GetCallback(), false); DriverStationSim::SetFmsAttached(true); DriverStationSim::NotifyNewData(); EXPECT_TRUE(DriverStationSim::GetFmsAttached()); - EXPECT_TRUE(DriverStation::IsFMSAttached()); + EXPECT_TRUE(RobotState::IsFMSAttached()); EXPECT_TRUE(callback.WasTriggered()); EXPECT_TRUE(callback.GetLastValue()); } @@ -100,21 +102,21 @@ TEST(DriverStationTest, FmsAttached) { TEST(DriverStationTest, DsAttached) { HAL_Initialize(500, 0); DriverStationSim::ResetData(); - DriverStation::RefreshData(); + wpi::internal::DriverStationBackend::RefreshData(); EXPECT_FALSE(DriverStationSim::GetDsAttached()); - EXPECT_FALSE(DriverStation::IsDSAttached()); + EXPECT_FALSE(RobotState::IsDSAttached()); DriverStationSim::NotifyNewData(); EXPECT_TRUE(DriverStationSim::GetDsAttached()); - EXPECT_TRUE(DriverStation::IsDSAttached()); + EXPECT_TRUE(RobotState::IsDSAttached()); BooleanCallback callback; auto cb = DriverStationSim::RegisterDsAttachedCallback(callback.GetCallback(), false); DriverStationSim::SetDsAttached(false); - DriverStation::RefreshData(); + wpi::internal::DriverStationBackend::RefreshData(); EXPECT_FALSE(DriverStationSim::GetDsAttached()); - EXPECT_FALSE(DriverStation::IsDSAttached()); + EXPECT_FALSE(RobotState::IsDSAttached()); EXPECT_TRUE(callback.WasTriggered()); EXPECT_FALSE(callback.GetLastValue()); } @@ -136,8 +138,8 @@ TEST(DriverStationTest, AllianceStationId) { DriverStationSim::SetAllianceStationId(allianceStation); wpi::sim::DriverStationSim::NotifyNewData(); EXPECT_EQ(allianceStation, DriverStationSim::GetAllianceStationId()); - EXPECT_FALSE(DriverStation::GetAlliance().has_value()); - EXPECT_FALSE(DriverStation::GetLocation().has_value()); + EXPECT_FALSE(MatchState::GetAlliance().has_value()); + EXPECT_FALSE(MatchState::GetLocation().has_value()); EXPECT_TRUE(callback.WasTriggered()); EXPECT_EQ(allianceStation, callback.GetLastValue()); @@ -146,8 +148,8 @@ TEST(DriverStationTest, AllianceStationId) { DriverStationSim::SetAllianceStationId(allianceStation); wpi::sim::DriverStationSim::NotifyNewData(); EXPECT_EQ(allianceStation, DriverStationSim::GetAllianceStationId()); - EXPECT_EQ(DriverStation::Alliance::BLUE, DriverStation::GetAlliance()); - EXPECT_EQ(1, DriverStation::GetLocation()); + EXPECT_EQ(Alliance::BLUE, MatchState::GetAlliance()); + EXPECT_EQ(1, MatchState::GetLocation()); EXPECT_TRUE(callback.WasTriggered()); EXPECT_EQ(allianceStation, callback.GetLastValue()); @@ -156,8 +158,8 @@ TEST(DriverStationTest, AllianceStationId) { DriverStationSim::SetAllianceStationId(allianceStation); wpi::sim::DriverStationSim::NotifyNewData(); EXPECT_EQ(allianceStation, DriverStationSim::GetAllianceStationId()); - EXPECT_EQ(DriverStation::Alliance::BLUE, DriverStation::GetAlliance()); - EXPECT_EQ(2, DriverStation::GetLocation()); + EXPECT_EQ(Alliance::BLUE, MatchState::GetAlliance()); + EXPECT_EQ(2, MatchState::GetLocation()); EXPECT_TRUE(callback.WasTriggered()); EXPECT_EQ(allianceStation, callback.GetLastValue()); @@ -166,8 +168,8 @@ TEST(DriverStationTest, AllianceStationId) { DriverStationSim::SetAllianceStationId(allianceStation); wpi::sim::DriverStationSim::NotifyNewData(); EXPECT_EQ(allianceStation, DriverStationSim::GetAllianceStationId()); - EXPECT_EQ(DriverStation::Alliance::BLUE, DriverStation::GetAlliance()); - EXPECT_EQ(3, DriverStation::GetLocation()); + EXPECT_EQ(Alliance::BLUE, MatchState::GetAlliance()); + EXPECT_EQ(3, MatchState::GetLocation()); EXPECT_TRUE(callback.WasTriggered()); EXPECT_EQ(allianceStation, callback.GetLastValue()); @@ -176,8 +178,8 @@ TEST(DriverStationTest, AllianceStationId) { DriverStationSim::SetAllianceStationId(allianceStation); wpi::sim::DriverStationSim::NotifyNewData(); EXPECT_EQ(allianceStation, DriverStationSim::GetAllianceStationId()); - EXPECT_EQ(DriverStation::Alliance::RED, DriverStation::GetAlliance()); - EXPECT_EQ(1, DriverStation::GetLocation()); + EXPECT_EQ(Alliance::RED, MatchState::GetAlliance()); + EXPECT_EQ(1, MatchState::GetLocation()); EXPECT_TRUE(callback.WasTriggered()); EXPECT_EQ(allianceStation, callback.GetLastValue()); @@ -186,8 +188,8 @@ TEST(DriverStationTest, AllianceStationId) { DriverStationSim::SetAllianceStationId(allianceStation); wpi::sim::DriverStationSim::NotifyNewData(); EXPECT_EQ(allianceStation, DriverStationSim::GetAllianceStationId()); - EXPECT_EQ(DriverStation::Alliance::RED, DriverStation::GetAlliance()); - EXPECT_EQ(2, DriverStation::GetLocation()); + EXPECT_EQ(Alliance::RED, MatchState::GetAlliance()); + EXPECT_EQ(2, MatchState::GetLocation()); EXPECT_TRUE(callback.WasTriggered()); EXPECT_EQ(allianceStation, callback.GetLastValue()); @@ -196,8 +198,8 @@ TEST(DriverStationTest, AllianceStationId) { DriverStationSim::SetAllianceStationId(allianceStation); wpi::sim::DriverStationSim::NotifyNewData(); EXPECT_EQ(allianceStation, DriverStationSim::GetAllianceStationId()); - EXPECT_EQ(DriverStation::Alliance::RED, DriverStation::GetAlliance()); - EXPECT_EQ(3, DriverStation::GetLocation()); + EXPECT_EQ(Alliance::RED, MatchState::GetAlliance()); + EXPECT_EQ(3, MatchState::GetLocation()); EXPECT_TRUE(callback.WasTriggered()); EXPECT_EQ(allianceStation, callback.GetLastValue()); } @@ -208,7 +210,7 @@ TEST(DriverStationTest, ReplayNumber) { DriverStationSim::SetReplayNumber(4); DriverStationSim::NotifyNewData(); - EXPECT_EQ(4, DriverStation::GetReplayNumber()); + EXPECT_EQ(4, MatchState::GetReplayNumber()); } TEST(DriverStationTest, MatchNumber) { @@ -217,7 +219,7 @@ TEST(DriverStationTest, MatchNumber) { DriverStationSim::SetMatchNumber(3); DriverStationSim::NotifyNewData(); - EXPECT_EQ(3, DriverStation::GetMatchNumber()); + EXPECT_EQ(3, MatchState::GetMatchNumber()); } TEST(DriverStationTest, MatchTime) { @@ -231,7 +233,7 @@ TEST(DriverStationTest, MatchTime) { DriverStationSim::SetMatchTime(kTestTime); wpi::sim::DriverStationSim::NotifyNewData(); EXPECT_EQ(kTestTime, DriverStationSim::GetMatchTime()); - EXPECT_EQ(kTestTime, DriverStation::GetMatchTime().value()); + EXPECT_EQ(kTestTime, MatchState::GetMatchTime().value()); EXPECT_TRUE(callback.WasTriggered()); EXPECT_EQ(kTestTime, callback.GetLastValue()); } @@ -243,7 +245,7 @@ TEST(DriverStationTest, SetGameData) { constexpr auto message = "Hello"; DriverStationSim::SetGameData(message); DriverStationSim::NotifyNewData(); - auto gameData = DriverStation::GetGameData(); + auto gameData = MatchState::GetGameData(); ASSERT_TRUE(gameData.has_value()); EXPECT_EQ(message, gameData.value()); } @@ -254,7 +256,7 @@ TEST(DriverStationTest, SetGameDataEmpty) { DriverStationSim::SetGameData(""); DriverStationSim::NotifyNewData(); - auto gameData = DriverStation::GetGameData(); + auto gameData = MatchState::GetGameData(); EXPECT_FALSE(gameData.has_value()); } @@ -265,5 +267,5 @@ TEST(DriverStationTest, SetEventName) { constexpr auto message = "The Best Event"; DriverStationSim::SetEventName(message); DriverStationSim::NotifyNewData(); - EXPECT_EQ(message, DriverStation::GetEventName()); + EXPECT_EQ(message, MatchState::GetEventName()); } diff --git a/wpilibc/src/test/python/test_opmode_robot.py b/wpilibc/src/test/python/test_opmode_robot.py index 088c0ff7b7..7586b5c98f 100644 --- a/wpilibc/src/test/python/test_opmode_robot.py +++ b/wpilibc/src/test/python/test_opmode_robot.py @@ -3,7 +3,7 @@ import threading from wpilib import simulation as wsim from wpimath.units import seconds from wpilib.opmoderobot import OpModeRobot -from wpilib import OpMode, DriverStation +from wpilib import OpMode, RobotState from hal._wpiHal import RobotMode from wpiutil import Color @@ -55,7 +55,7 @@ def sim_timing_setup(): wsim.setProgramStarted(False) yield wsim.resumeTiming() - DriverStation.clearOpModes() + RobotState.clearOpModes() def test_add_op_mode(): diff --git a/wpilibcExamples/src/main/cpp/snippets/DigitalCommunication/cpp/Robot.cpp b/wpilibcExamples/src/main/cpp/snippets/DigitalCommunication/cpp/Robot.cpp index 2dcf3c4a71..0e78d207d9 100644 --- a/wpilibcExamples/src/main/cpp/snippets/DigitalCommunication/cpp/Robot.cpp +++ b/wpilibcExamples/src/main/cpp/snippets/DigitalCommunication/cpp/Robot.cpp @@ -4,21 +4,21 @@ #include "Robot.hpp" -#include "wpi/driverstation/DriverStation.hpp" +#include "wpi/driverstation/MatchState.hpp" +#include "wpi/driverstation/RobotState.hpp" void Robot::RobotPeriodic() { // pull alliance port high if on red alliance, pull low if on blue alliance - m_allianceOutput.Set(wpi::DriverStation::GetAlliance() == - wpi::DriverStation::Alliance::RED); + m_allianceOutput.Set(wpi::MatchState::GetAlliance() == wpi::Alliance::RED); // pull enabled port high if enabled, low if disabled - m_enabledOutput.Set(wpi::DriverStation::IsEnabled()); + m_enabledOutput.Set(wpi::RobotState::IsEnabled()); // pull auto port high if in autonomous, low if in teleop (or disabled) - m_autonomousOutput.Set(wpi::DriverStation::IsAutonomous()); + m_autonomousOutput.Set(wpi::RobotState::IsAutonomous()); // pull alert port high if match time remaining is between 30 and 25 seconds - auto matchTime = wpi::DriverStation::GetMatchTime(); + auto matchTime = wpi::MatchState::GetMatchTime(); m_alertOutput.Set(matchTime <= 30_s && matchTime >= 25_s); } diff --git a/wpilibcExamples/src/main/cpp/snippets/I2CCommunication/cpp/Robot.cpp b/wpilibcExamples/src/main/cpp/snippets/I2CCommunication/cpp/Robot.cpp index 46977bdd62..f211128810 100644 --- a/wpilibcExamples/src/main/cpp/snippets/I2CCommunication/cpp/Robot.cpp +++ b/wpilibcExamples/src/main/cpp/snippets/I2CCommunication/cpp/Robot.cpp @@ -8,7 +8,8 @@ #include -#include "wpi/driverstation/DriverStation.hpp" +#include "wpi/driverstation/MatchState.hpp" +#include "wpi/driverstation/RobotState.hpp" #include "wpi/system/Timer.hpp" void Robot::RobotPeriodic() { @@ -23,20 +24,19 @@ void Robot::RobotPeriodic() { // alliance, enabled in teleop mode, with 43 seconds left in the match. std::string allianceString = "U"; - auto alliance = wpi::DriverStation::GetAlliance(); + auto alliance = wpi::MatchState::GetAlliance(); if (alliance.has_value()) { - if (alliance == wpi::DriverStation::Alliance::RED) { + if (alliance == wpi::Alliance::RED) { allianceString = "R"; } else { allianceString = "B"; } } - auto string = - fmt::format("{}{}{}{:03}", allianceString, - wpi::DriverStation::IsEnabled() ? "E" : "D", - wpi::DriverStation::IsAutonomous() ? "A" : "T", - static_cast(wpi::Timer::GetMatchTime().value())); + auto string = fmt::format( + "{}{}{}{:03}", allianceString, wpi::RobotState::IsEnabled() ? "E" : "D", + wpi::RobotState::IsAutonomous() ? "A" : "T", + static_cast(wpi::Timer::GetMatchTime().value())); arduino.WriteBulk(reinterpret_cast(string.data()), string.size()); } diff --git a/wpilibcExamples/src/main/cpp/templates/robotbaseskeleton/cpp/Robot.cpp b/wpilibcExamples/src/main/cpp/templates/robotbaseskeleton/cpp/Robot.cpp index 96991922d4..3f510c8213 100644 --- a/wpilibcExamples/src/main/cpp/templates/robotbaseskeleton/cpp/Robot.cpp +++ b/wpilibcExamples/src/main/cpp/templates/robotbaseskeleton/cpp/Robot.cpp @@ -4,7 +4,8 @@ #include "Robot.hpp" -#include "wpi/driverstation/DriverStation.hpp" +#include "wpi/driverstation/RobotState.hpp" +#include "wpi/driverstation/internal/DriverStationBackend.hpp" #include "wpi/hal/DriverStation.h" #include "wpi/internal/DriverStationModeThread.hpp" @@ -22,19 +23,20 @@ void Robot::StartCompetition() { wpi::internal::DriverStationModeThread modeThread{wpi::hal::GetControlWord()}; // Create an opmode per robot mode - wpi::DriverStation::AddOpMode(wpi::RobotMode::AUTONOMOUS, "Auto"); - wpi::DriverStation::AddOpMode(wpi::RobotMode::TELEOPERATED, "Teleop"); - wpi::DriverStation::AddOpMode(wpi::RobotMode::TEST, "Test"); - wpi::DriverStation::PublishOpModes(); + wpi::RobotState::AddOpMode(wpi::RobotMode::AUTONOMOUS, "Auto"); + wpi::RobotState::AddOpMode(wpi::RobotMode::TELEOPERATED, "Teleop"); + wpi::RobotState::AddOpMode(wpi::RobotMode::TEST, "Test"); + wpi::RobotState::PublishOpModes(); wpi::util::Event event{false, false}; - wpi::DriverStation::ProvideRefreshedDataEventHandle(event.GetHandle()); + wpi::internal::DriverStationBackend::ProvideRefreshedDataEventHandle( + event.GetHandle()); // Tell the DS that the robot is ready to be enabled - wpi::DriverStation::ObserveUserProgramStarting(); + wpi::internal::DriverStationBackend::ObserveUserProgramStarting(); while (!m_exit) { - modeThread.InControl(wpi::DriverStation::GetControlWord()); + modeThread.InControl(wpi::internal::DriverStationBackend::GetControlWord()); if (IsDisabled()) { Disabled(); while (IsDisabled()) { diff --git a/wpilibj/src/main/java/org/wpilib/driverstation/Alliance.java b/wpilibj/src/main/java/org/wpilib/driverstation/Alliance.java new file mode 100644 index 0000000000..99f78a4011 --- /dev/null +++ b/wpilibj/src/main/java/org/wpilib/driverstation/Alliance.java @@ -0,0 +1,13 @@ +// 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.driverstation; + +/** The robot alliance that the robot is a part of. */ +public enum Alliance { + /** Red alliance. */ + RED, + /** Blue alliance. */ + BLUE +} diff --git a/wpilibj/src/main/java/org/wpilib/driverstation/DefaultUserControls.java b/wpilibj/src/main/java/org/wpilib/driverstation/DefaultUserControls.java index 3416bd38fe..e788fed86a 100644 --- a/wpilibj/src/main/java/org/wpilib/driverstation/DefaultUserControls.java +++ b/wpilibj/src/main/java/org/wpilib/driverstation/DefaultUserControls.java @@ -4,6 +4,8 @@ package org.wpilib.driverstation; +import org.wpilib.driverstation.internal.DriverStationBackend; + /** * A default implementation of UserControls that provides Gamepad instances for each of the 6 * joystick ports provided by the DS. @@ -13,7 +15,7 @@ public class DefaultUserControls implements UserControls { /** Constructs a DefaultUserControls instance with Gamepads for each port. */ public DefaultUserControls() { - m_gamepads = new Gamepad[DriverStation.kJoystickPorts]; + m_gamepads = new Gamepad[DriverStationBackend.JOYSTICK_PORTS]; for (int i = 0; i < m_gamepads.length; i++) { m_gamepads[i] = new Gamepad(i); } diff --git a/wpilibj/src/main/java/org/wpilib/driverstation/DriverStation.java b/wpilibj/src/main/java/org/wpilib/driverstation/DriverStation.java index 34c3e4f1c3..c5c402b6fa 100644 --- a/wpilibj/src/main/java/org/wpilib/driverstation/DriverStation.java +++ b/wpilibj/src/main/java/org/wpilib/driverstation/DriverStation.java @@ -4,1969 +4,13 @@ package org.wpilib.driverstation; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.OptionalDouble; -import java.util.OptionalInt; -import java.util.concurrent.locks.ReentrantLock; -import org.wpilib.datalog.BooleanArrayLogEntry; import org.wpilib.datalog.DataLog; -import org.wpilib.datalog.FloatArrayLogEntry; -import org.wpilib.datalog.IntegerArrayLogEntry; -import org.wpilib.datalog.StringLogEntry; -import org.wpilib.datalog.StructLogEntry; -import org.wpilib.framework.OpModeRobot; -import org.wpilib.framework.TimedRobot; -import org.wpilib.hardware.hal.AllianceStationID; -import org.wpilib.hardware.hal.ControlWord; -import org.wpilib.hardware.hal.DriverStationJNI; -import org.wpilib.hardware.hal.HAL; -import org.wpilib.hardware.hal.MatchInfoData; -import org.wpilib.hardware.hal.OpModeOption; -import org.wpilib.hardware.hal.RobotMode; -import org.wpilib.math.geometry.Rotation2d; -import org.wpilib.networktables.BooleanPublisher; -import org.wpilib.networktables.IntegerPublisher; -import org.wpilib.networktables.NetworkTableInstance; -import org.wpilib.networktables.StringPublisher; -import org.wpilib.networktables.StringTopic; -import org.wpilib.networktables.StructPublisher; -import org.wpilib.system.Timer; -import org.wpilib.util.Color; -import org.wpilib.util.WPIUtilJNI; -import org.wpilib.util.concurrent.EventVector; +import org.wpilib.driverstation.internal.DriverStationBackend; -/** Provide access to the network communication data to / from the Driver Station. */ +/** Provides access to Driver Station functionality. */ public final class DriverStation { - /** Number of Joystick ports. */ - public static final int kJoystickPorts = 6; - - private static final long[] m_metadataCache = new long[7]; - private static final float[] m_touchpadFingersCache = new float[8]; - - private static int availableToCount(long available) { - // Top bit has to be set - if (available < 0) { - return 64; - } - - int count = 0; - - // Top bit not set, we will eventually get a 0 bit - while ((available & 0x1) != 0) { - count++; - available >>= 1; - } - return count; - } - - private static final class HALJoystickTouchpadFinger { - public float m_x; - public float m_y; - public boolean m_down; - } - - private static class HALJoystickTouchpad { - public final HALJoystickTouchpadFinger[] m_fingers = - new HALJoystickTouchpadFinger[DriverStationJNI.MAX_JOYSTICK_TOUCHPAD_FINGERS]; - public int m_count; - - HALJoystickTouchpad() { - for (int i = 0; i < m_fingers.length; i++) { - m_fingers[i] = new HALJoystickTouchpadFinger(); - } - } - } - - private static class HALJoystickTouchpads { - public final HALJoystickTouchpad[] m_touchpads = - new HALJoystickTouchpad[DriverStationJNI.MAX_JOYSTICK_TOUCHPADS]; - public int m_count; - - HALJoystickTouchpads() { - for (int i = 0; i < m_touchpads.length; i++) { - m_touchpads[i] = new HALJoystickTouchpad(); - } - } - } - - private static final class HALJoystickButtons { - public long m_buttons; - public long m_available; - } - - private static class HALJoystickAxes { - public final float[] m_axes; - public int m_available; - - HALJoystickAxes(int count) { - m_axes = new float[count]; - } - } - - private static class HALJoystickAxesRaw { - public final short[] m_axes; - - @SuppressWarnings("unused") - public int m_available; - - HALJoystickAxesRaw(int count) { - m_axes = new short[count]; - } - } - - private static class HALJoystickPOVs { - public final byte[] m_povs; - public int m_available; - - HALJoystickPOVs(int count) { - m_povs = new byte[count]; - for (int i = 0; i < count; i++) { - m_povs[i] = 0; - } - } - } - - /** The robot alliance that the robot is a part of. */ - public enum Alliance { - /** Red alliance. */ - RED, - /** Blue alliance. */ - BLUE - } - - /** The type of robot match that the robot is part of. */ - public enum MatchType { - /** None. */ - NONE, - /** Practice. */ - PRACTICE, - /** Qualification. */ - QUALIFICATION, - /** Elimination. */ - ELIMINATION - } - - /** Represents a finger on a touchpad. */ - @SuppressWarnings("MemberName") - public static class TouchpadFinger { - /** Whether the finger is touching the touchpad. */ - public final boolean down; - - /** The x position of the finger. 0 is at top left. */ - public final float x; - - /** The y position of the finger. 0 is at top left. */ - public final float y; - - /** - * Creates a TouchpadFinger object. - * - * @param down Whether the finger is touching the touchpad. - * @param x The x position of the finger. - * @param y The y position of the finger. - */ - public TouchpadFinger(boolean down, float x, float y) { - this.x = x; - this.y = y; - this.down = down; - } - } - - /** A controller POV direction. */ - public enum POVDirection { - /** POV center. */ - CENTER(0x00), - /** POV up. */ - UP(0x01), - /** POV up right. */ - UP_RIGHT(0x01 | 0x02), - /** POV right. */ - RIGHT(0x02), - /** POV down right. */ - DOWN_RIGHT(0x02 | 0x04), - /** POV down. */ - DOWN(0x04), - /** POV down left. */ - DOWN_LEFT(0x04 | 0x08), - /** POV left. */ - LEFT(0x08), - /** POV up left. */ - UP_LEFT(0x01 | 0x08); - - private static final double INVALID_POV_VALUE_INTERVAL = 1.0; - private static double s_nextMessageTime; - - /** - * Converts a byte value into a POVDirection enum value. - * - * @param value The byte value to convert. - * @return The corresponding POVDirection enum value. - * @throws IllegalArgumentException If value does not correspond to a POVDirection. - */ - private static POVDirection of(byte value) { - for (var direction : values()) { - if (direction.value == value) { - return direction; - } - } - double currentTime = Timer.getTimestamp(); - if (currentTime > s_nextMessageTime) { - reportError("Invalid POV value " + value + "!", false); - s_nextMessageTime = currentTime + INVALID_POV_VALUE_INTERVAL; - } - return CENTER; - } - - /** The corresponding HAL value. */ - public final byte value; - - POVDirection(int value) { - this.value = (byte) value; - } - - /** - * Gets the angle of a POVDirection. - * - * @return The angle clockwise from straight up, or Optional.empty() if this POVDirection is - * Center. - */ - public Optional getAngle() { - return switch (this) { - case CENTER -> Optional.empty(); - case UP -> Optional.of(Rotation2d.fromDegrees(0)); - case UP_RIGHT -> Optional.of(Rotation2d.fromDegrees(45)); - case RIGHT -> Optional.of(Rotation2d.fromDegrees(90)); - case DOWN_RIGHT -> Optional.of(Rotation2d.fromDegrees(135)); - case DOWN -> Optional.of(Rotation2d.fromDegrees(180)); - case DOWN_LEFT -> Optional.of(Rotation2d.fromDegrees(225)); - case LEFT -> Optional.of(Rotation2d.fromDegrees(270)); - case UP_LEFT -> Optional.of(Rotation2d.fromDegrees(315)); - }; - } - } - - private static final double JOYSTICK_UNPLUGGED_MESSAGE_INTERVAL = 1.0; - private static double m_nextMessageTime; - - private static String opModeToString(long id) { - if (id == 0) { - return ""; - } - m_opModesMutex.lock(); - try { - OpModeOption option = m_opModes.get(id); - if (option != null) { - return option.name; - } - } finally { - m_opModesMutex.unlock(); - } - return "<" + id + ">"; - } - - @SuppressWarnings("MemberName") - private static class MatchDataSender { - private static final String kSmartDashboardType = "FMSInfo"; - - final StringPublisher gameData; - final StringPublisher eventName; - final IntegerPublisher matchNumber; - final IntegerPublisher replayNumber; - final IntegerPublisher matchType; - final BooleanPublisher alliance; - final IntegerPublisher station; - final StructPublisher controlWord; - final StringPublisher opMode; - boolean oldIsRedAlliance = true; - int oldStationNumber = 1; - String oldEventName = ""; - String oldGameData = ""; - int oldMatchNumber; - int oldReplayNumber; - int oldMatchType; - final ControlWord oldControlWord = new ControlWord(); - final ControlWord currentControlWord = new ControlWord(); - - MatchDataSender() { - var table = NetworkTableInstance.getDefault().getTable("FMSInfo"); - table - .getStringTopic(".type") - .publishEx( - StringTopic.TYPE_STRING, "{\"SmartDashboard\":\"" + kSmartDashboardType + "\"}") - .set(kSmartDashboardType); - gameData = table.getStringTopic("GameData").publish(); - gameData.set(""); - eventName = table.getStringTopic("EventName").publish(); - eventName.set(""); - matchNumber = table.getIntegerTopic("MatchNumber").publish(); - matchNumber.set(0); - replayNumber = table.getIntegerTopic("ReplayNumber").publish(); - replayNumber.set(0); - matchType = table.getIntegerTopic("MatchType").publish(); - matchType.set(0); - alliance = table.getBooleanTopic("IsRedAlliance").publish(); - alliance.set(true); - station = table.getIntegerTopic("StationNumber").publish(); - station.set(1); - controlWord = table.getStructTopic("ControlWord", ControlWord.struct).publish(); - controlWord.set(oldControlWord); - opMode = table.getStringTopic("OpMode").publish(); - opMode.set(""); - } - - @SuppressWarnings("VariableDeclarationUsageDistance") - private void sendMatchData() { - AllianceStationID allianceID = DriverStationJNI.getAllianceStation(); - final int stationNumber = - switch (allianceID) { - case BLUE_1, RED_1 -> 1; - case BLUE_2, RED_2 -> 2; - case BLUE_3, RED_3, UNKNOWN -> 3; - }; - final boolean isRedAlliance = - switch (allianceID) { - case BLUE_1, BLUE_2, BLUE_3 -> false; - case RED_1, RED_2, RED_3, UNKNOWN -> true; - }; - - String currentEventName; - String currentGameData; - int currentMatchNumber; - int currentReplayNumber; - int currentMatchType; - m_cacheDataMutex.lock(); - try { - currentEventName = DriverStation.m_matchInfo.eventName; - currentGameData = DriverStation.m_gameData; - currentMatchNumber = DriverStation.m_matchInfo.matchNumber; - currentReplayNumber = DriverStation.m_matchInfo.replayNumber; - currentMatchType = DriverStation.m_matchInfo.matchType; - } finally { - m_cacheDataMutex.unlock(); - } - DriverStationJNI.getControlWord(currentControlWord); - - if (oldIsRedAlliance != isRedAlliance) { - alliance.set(isRedAlliance); - oldIsRedAlliance = isRedAlliance; - } - if (oldStationNumber != stationNumber) { - station.set(stationNumber); - oldStationNumber = stationNumber; - } - if (!oldEventName.equals(currentEventName)) { - eventName.set(currentEventName); - oldEventName = currentEventName; - } - if (!oldGameData.equals(currentGameData)) { - gameData.set(currentGameData); - oldGameData = currentGameData; - } - if (currentMatchNumber != oldMatchNumber) { - matchNumber.set(currentMatchNumber); - oldMatchNumber = currentMatchNumber; - } - if (currentReplayNumber != oldReplayNumber) { - replayNumber.set(currentReplayNumber); - oldReplayNumber = currentReplayNumber; - } - if (currentMatchType != oldMatchType) { - matchType.set(currentMatchType); - oldMatchType = currentMatchType; - } - if (!currentControlWord.equals(oldControlWord)) { - long currentOpModeId = currentControlWord.getOpModeId(); - if (currentOpModeId != oldControlWord.getOpModeId()) { - opMode.set(opModeToString(currentOpModeId)); - } - controlWord.set(currentControlWord); - oldControlWord.update(currentControlWord); - } - } - } - - private static class JoystickLogSender { - JoystickLogSender(DataLog log, int stick, long timestamp) { - m_stick = stick; - - m_logButtons = new BooleanArrayLogEntry(log, "DS:joystick" + stick + "/buttons", timestamp); - m_logAxes = new FloatArrayLogEntry(log, "DS:joystick" + stick + "/axes", timestamp); - m_logPOVs = new IntegerArrayLogEntry(log, "DS:joystick" + stick + "/povs", timestamp); - - appendButtons(m_joystickButtons[m_stick], timestamp); - appendAxes(m_joystickAxes[m_stick], timestamp); - appendPOVs(m_joystickPOVs[m_stick], timestamp); - } - - public void send(long timestamp) { - HALJoystickButtons buttons = m_joystickButtons[m_stick]; - if (buttons.m_available != m_prevButtons.m_available - || buttons.m_buttons != m_prevButtons.m_buttons) { - appendButtons(buttons, timestamp); - } - - HALJoystickAxes axes = m_joystickAxes[m_stick]; - int available = axes.m_available; - boolean needToLog = false; - if (available != m_prevAxes.m_available) { - needToLog = true; - } else { - for (int i = 0; i < m_prevAxes.m_axes.length; i++) { - if (axes.m_axes[i] != m_prevAxes.m_axes[i]) { - needToLog = true; - break; - } - } - } - if (needToLog) { - appendAxes(axes, timestamp); - } - - HALJoystickPOVs povs = m_joystickPOVs[m_stick]; - available = m_joystickPOVs[m_stick].m_available; - needToLog = false; - if (available != m_prevPOVs.m_available) { - needToLog = true; - } else { - for (int i = 0; i < m_prevPOVs.m_povs.length; i++) { - if (povs.m_povs[i] != m_prevPOVs.m_povs[i]) { - needToLog = true; - break; - } - } - } - if (needToLog) { - appendPOVs(povs, timestamp); - } - } - - void appendButtons(HALJoystickButtons buttons, long timestamp) { - int count = availableToCount(buttons.m_available); - if (m_sizedButtons == null || m_sizedButtons.length != count) { - m_sizedButtons = new boolean[count]; - } - long buttonsValue = buttons.m_buttons; - for (int i = 0; i < count; i++) { - m_sizedButtons[i] = (buttonsValue & (1L << i)) != 0; - } - m_logButtons.append(m_sizedButtons, timestamp); - m_prevButtons.m_available = buttons.m_available; - m_prevButtons.m_buttons = buttons.m_buttons; - } - - void appendAxes(HALJoystickAxes axes, long timestamp) { - int count = availableToCount(axes.m_available); - if (m_sizedAxes == null || m_sizedAxes.length != count) { - m_sizedAxes = new float[count]; - } - System.arraycopy(axes.m_axes, 0, m_sizedAxes, 0, count); - m_logAxes.append(m_sizedAxes, timestamp); - m_prevAxes.m_available = axes.m_available; - System.arraycopy(axes.m_axes, 0, m_prevAxes.m_axes, 0, count); - } - - void appendPOVs(HALJoystickPOVs povs, long timestamp) { - int count = availableToCount(povs.m_available); - if (m_sizedPOVs == null || m_sizedPOVs.length != count) { - m_sizedPOVs = new long[count]; - } - for (int i = 0; i < count; i++) { - m_sizedPOVs[i] = povs.m_povs[i]; - } - m_logPOVs.append(m_sizedPOVs, timestamp); - m_prevPOVs.m_available = povs.m_available; - System.arraycopy(povs.m_povs, 0, m_prevPOVs.m_povs, 0, count); - } - - final int m_stick; - boolean[] m_sizedButtons; - float[] m_sizedAxes; - long[] m_sizedPOVs; - final HALJoystickButtons m_prevButtons = new HALJoystickButtons(); - final HALJoystickAxes m_prevAxes = new HALJoystickAxes(DriverStationJNI.MAX_JOYSTICK_AXES); - final HALJoystickPOVs m_prevPOVs = new HALJoystickPOVs(DriverStationJNI.MAX_JOYSTICK_POVS); - final BooleanArrayLogEntry m_logButtons; - final FloatArrayLogEntry m_logAxes; - final IntegerArrayLogEntry m_logPOVs; - } - - private static class DataLogSender { - DataLogSender(DataLog log, boolean logJoysticks, long timestamp) { - m_logControlWord = - StructLogEntry.create(log, "DS:controlWord", ControlWord.struct, timestamp); - - // append initial control word value - m_logControlWord.append(m_controlWordCache, timestamp); - m_oldControlWord.update(m_controlWordCache); - - // append initial opmode value - m_logOpMode = new StringLogEntry(log, "DS:opMode", timestamp); - m_logOpMode.append(m_opModeCache, timestamp); - - if (logJoysticks) { - m_joysticks = new JoystickLogSender[kJoystickPorts]; - for (int i = 0; i < kJoystickPorts; i++) { - m_joysticks[i] = new JoystickLogSender(log, i, timestamp); - } - } else { - m_joysticks = new JoystickLogSender[0]; - } - } - - public void send(long timestamp) { - // append control word value changes - if (!m_controlWordCache.equals(m_oldControlWord)) { - // append opmode value changes - long opModeId = m_controlWordCache.getOpModeId(); - if (opModeId != m_oldControlWord.getOpModeId()) { - m_logOpMode.append(m_opModeCache, timestamp); - } - - m_logControlWord.append(m_controlWordCache, timestamp); - m_oldControlWord.update(m_controlWordCache); - } - - // append joystick value changes - for (JoystickLogSender joystick : m_joysticks) { - joystick.send(timestamp); - } - } - - final ControlWord m_oldControlWord = new ControlWord(); - final StructLogEntry m_logControlWord; - final StringLogEntry m_logOpMode; - - final JoystickLogSender[] m_joysticks; - } - - // Joystick User Data - private static HALJoystickAxes[] m_joystickAxes = new HALJoystickAxes[kJoystickPorts]; - private static HALJoystickAxesRaw[] m_joystickAxesRaw = new HALJoystickAxesRaw[kJoystickPorts]; - private static HALJoystickPOVs[] m_joystickPOVs = new HALJoystickPOVs[kJoystickPorts]; - private static HALJoystickButtons[] m_joystickButtons = new HALJoystickButtons[kJoystickPorts]; - private static HALJoystickTouchpads[] m_joystickTouchpads = - new HALJoystickTouchpads[kJoystickPorts]; - private static MatchInfoData m_matchInfo = new MatchInfoData(); - private static String m_gameData = ""; - private static ControlWord m_controlWord = new ControlWord(); - private static String m_opMode = ""; - private static EventVector m_refreshEvents = new EventVector(); - - // Joystick Cached Data - private static HALJoystickAxes[] m_joystickAxesCache = new HALJoystickAxes[kJoystickPorts]; - private static HALJoystickAxesRaw[] m_joystickAxesRawCache = - new HALJoystickAxesRaw[kJoystickPorts]; - private static HALJoystickPOVs[] m_joystickPOVsCache = new HALJoystickPOVs[kJoystickPorts]; - private static HALJoystickButtons[] m_joystickButtonsCache = - new HALJoystickButtons[kJoystickPorts]; - private static HALJoystickTouchpads[] m_joystickTouchpadsCache = - new HALJoystickTouchpads[kJoystickPorts]; - private static MatchInfoData m_matchInfoCache = new MatchInfoData(); - private static String m_gameDataCache = ""; - private static ControlWord m_controlWordCache = new ControlWord(); - - private static String m_opModeCache = ""; - - // Joystick button rising/falling edge flags - private static long[] m_joystickButtonsPressed = new long[kJoystickPorts]; - private static long[] m_joystickButtonsReleased = new long[kJoystickPorts]; - - private static final MatchDataSender m_matchDataSender; - private static DataLogSender m_dataLogSender; - - private static final ReentrantLock m_cacheDataMutex = new ReentrantLock(); - - private static boolean m_silenceJoystickWarning; - - private static boolean m_userProgramStarted = false; - private static final Map m_opModes = new HashMap<>(); - private static final ReentrantLock m_opModesMutex = new ReentrantLock(); - - /** - * DriverStation constructor. - * - *

The single DriverStation instance is created statically with the instance static member - * variable. - */ private DriverStation() {} - static { - HAL.initialize(500, 0); - - for (int i = 0; i < kJoystickPorts; i++) { - m_joystickButtons[i] = new HALJoystickButtons(); - m_joystickAxes[i] = new HALJoystickAxes(DriverStationJNI.MAX_JOYSTICK_AXES); - m_joystickAxesRaw[i] = new HALJoystickAxesRaw(DriverStationJNI.MAX_JOYSTICK_AXES); - m_joystickPOVs[i] = new HALJoystickPOVs(DriverStationJNI.MAX_JOYSTICK_POVS); - m_joystickTouchpads[i] = new HALJoystickTouchpads(); - - m_joystickButtonsCache[i] = new HALJoystickButtons(); - m_joystickAxesCache[i] = new HALJoystickAxes(DriverStationJNI.MAX_JOYSTICK_AXES); - m_joystickAxesRawCache[i] = new HALJoystickAxesRaw(DriverStationJNI.MAX_JOYSTICK_AXES); - m_joystickPOVsCache[i] = new HALJoystickPOVs(DriverStationJNI.MAX_JOYSTICK_POVS); - m_joystickTouchpadsCache[i] = new HALJoystickTouchpads(); - } - - m_matchDataSender = new MatchDataSender(); - } - - /** - * Report error to Driver Station. Optionally appends Stack trace to error message. - * - * @param error The error to report. - * @param printTrace If true, append stack trace to error string - */ - public static void reportError(String error, boolean printTrace) { - reportErrorImpl(true, 1, error, printTrace); - } - - /** - * Report error to Driver Station. Appends provided stack trace to error message. - * - * @param error The error to report. - * @param stackTrace The stack trace to append - */ - public static void reportError(String error, StackTraceElement[] stackTrace) { - reportErrorImpl(true, 1, error, stackTrace); - } - - /** - * Report warning to Driver Station. Optionally appends Stack trace to warning message. - * - * @param warning The warning to report. - * @param printTrace If true, append stack trace to warning string - */ - public static void reportWarning(String warning, boolean printTrace) { - reportErrorImpl(false, 1, warning, printTrace); - } - - /** - * Report warning to Driver Station. Appends provided stack trace to warning message. - * - * @param warning The warning to report. - * @param stackTrace The stack trace to append - */ - public static void reportWarning(String warning, StackTraceElement[] stackTrace) { - reportErrorImpl(false, 1, warning, stackTrace); - } - - private static void reportErrorImpl(boolean isError, int code, String error, boolean printTrace) { - reportErrorImpl(isError, code, error, printTrace, Thread.currentThread().getStackTrace(), 3); - } - - private static void reportErrorImpl( - boolean isError, int code, String error, StackTraceElement[] stackTrace) { - reportErrorImpl(isError, code, error, true, stackTrace, 0); - } - - private static void reportErrorImpl( - boolean isError, - int code, - String error, - boolean printTrace, - StackTraceElement[] stackTrace, - int stackTraceFirst) { - String locString; - if (stackTrace.length >= stackTraceFirst + 1) { - locString = stackTrace[stackTraceFirst].toString(); - } else { - locString = ""; - } - StringBuilder traceString = new StringBuilder(); - if (printTrace) { - boolean haveLoc = false; - for (int i = stackTraceFirst; i < stackTrace.length; i++) { - String loc = stackTrace[i].toString(); - traceString.append("\tat ").append(loc).append('\n'); - // get first user function - if (!haveLoc && !loc.startsWith("org.wpilib")) { - locString = loc; - haveLoc = true; - } - } - } - DriverStationJNI.sendError( - isError, code, false, error, locString, traceString.toString(), true); - } - - /** - * The state of one joystick button. - * - * @param stick The joystick to read. - * @param button The button index. - * @return The state of the joystick button. - */ - public static boolean getStickButton(final int stick, final int button) { - if (stick < 0 || stick >= kJoystickPorts) { - throw new IllegalArgumentException("Joystick index is out of range, should be 0-5"); - } - if (button < 0 || button >= DriverStationJNI.MAX_JOYSTICK_BUTTONS) { - throw new IllegalArgumentException("Joystick Button is out of range"); - } - - long mask = 1L << button; - - m_cacheDataMutex.lock(); - try { - if ((m_joystickButtons[stick].m_available & mask) != 0) { - return (m_joystickButtons[stick].m_buttons & mask) != 0; - } - } finally { - m_cacheDataMutex.unlock(); - } - - reportJoystickWarning( - stick, "Joystick Button " + button + " on port " + stick + " not available"); - return false; - } - - /** - * The state of one joystick button if available. - * - * @param stick The joystick to read. - * @param button The button index. - * @return The state of the joystick button, or false if the button is not available. - */ - public static Optional getStickButtonIfAvailable(final int stick, final int button) { - if (stick < 0 || stick >= kJoystickPorts) { - throw new IllegalArgumentException("Joystick index is out of range, should be 0-5"); - } - if (button < 0 || button >= DriverStationJNI.MAX_JOYSTICK_BUTTONS) { - throw new IllegalArgumentException("Joystick Button is out of range"); - } - - long mask = 1L << button; - - m_cacheDataMutex.lock(); - try { - if ((m_joystickButtons[stick].m_available & mask) != 0) { - return Optional.of((m_joystickButtons[stick].m_buttons & mask) != 0); - } - } finally { - m_cacheDataMutex.unlock(); - } - return Optional.empty(); - } - - /** - * Whether one joystick button was pressed since the last check. - * - * @param stick The joystick to read. - * @param button The button index. - * @return Whether the joystick button was pressed since the last check. - */ - public static boolean getStickButtonPressed(final int stick, final int button) { - if (stick < 0 || stick >= kJoystickPorts) { - throw new IllegalArgumentException("Joystick index is out of range, should be 0-5"); - } - if (button < 0 || button >= DriverStationJNI.MAX_JOYSTICK_BUTTONS) { - throw new IllegalArgumentException("Joystick Button is out of range"); - } - - long mask = 1L << button; - - m_cacheDataMutex.lock(); - try { - if ((m_joystickButtons[stick].m_available & mask) != 0) { - // If button was pressed, clear flag and return true - if ((m_joystickButtonsPressed[stick] & mask) != 0) { - m_joystickButtonsPressed[stick] &= ~mask; - return true; - } else { - return false; - } - } - } finally { - m_cacheDataMutex.unlock(); - } - - reportJoystickWarning( - stick, "Joystick Button " + button + " on port " + stick + " not available"); - return false; - } - - /** - * Whether one joystick button was released since the last check. - * - * @param stick The joystick to read. - * @param button The button index, beginning at 0. - * @return Whether the joystick button was released since the last check. - */ - public static boolean getStickButtonReleased(final int stick, final int button) { - if (stick < 0 || stick >= kJoystickPorts) { - throw new IllegalArgumentException("Joystick index is out of range, should be 0-5"); - } - if (button < 0 || button >= DriverStationJNI.MAX_JOYSTICK_BUTTONS) { - throw new IllegalArgumentException("Joystick Button is out of range"); - } - - long mask = 1L << button; - - m_cacheDataMutex.lock(); - try { - if ((m_joystickButtons[stick].m_available & mask) != 0) { - // If button was released, clear flag and return true - if ((m_joystickButtonsReleased[stick] & mask) != 0) { - m_joystickButtonsReleased[stick] &= ~mask; - return true; - } else { - return false; - } - } - } finally { - m_cacheDataMutex.unlock(); - } - - reportJoystickWarning( - stick, "Joystick Button " + button + " on port " + stick + " not available"); - return false; - } - - /** - * Get the value of the axis on a joystick. This depends on the mapping of the joystick connected - * to the specified port. - * - * @param stick The joystick to read. - * @param axis The analog axis value to read from the joystick. - * @return The value of the axis on the joystick. - */ - public static double getStickAxis(int stick, int axis) { - if (stick < 0 || stick >= kJoystickPorts) { - throw new IllegalArgumentException("Joystick index is out of range, should be 0-5"); - } - if (axis < 0 || axis >= DriverStationJNI.MAX_JOYSTICK_AXES) { - throw new IllegalArgumentException("Joystick axis is out of range"); - } - - int mask = 1 << axis; - - m_cacheDataMutex.lock(); - try { - if ((m_joystickAxes[stick].m_available & mask) != 0) { - return m_joystickAxes[stick].m_axes[axis]; - } - } finally { - m_cacheDataMutex.unlock(); - } - - reportJoystickWarning(stick, "Joystick axis " + axis + " on port " + stick + " not available"); - return 0.0; - } - - /** - * Get the state of a touchpad finger on the joystick. - * - * @param stick The joystick to read. - * @param touchpad The touchpad to read. - * @param finger The finger to read. - * @return the state of the touchpad finger. - */ - public static TouchpadFinger getStickTouchpadFinger(int stick, int touchpad, int finger) { - if (stick < 0 || stick >= kJoystickPorts) { - throw new IllegalArgumentException("Joystick index is out of range, should be 0-5"); - } - if (touchpad < 0 || touchpad >= DriverStationJNI.MAX_JOYSTICK_TOUCHPADS) { - throw new IllegalArgumentException("Joystick touchpad is out of range"); - } - if (finger < 0 || finger >= DriverStationJNI.MAX_JOYSTICK_TOUCHPAD_FINGERS) { - throw new IllegalArgumentException("Joystick touchpad finger is out of range"); - } - - int touchpadCount; - m_cacheDataMutex.lock(); - try { - touchpadCount = m_joystickTouchpads[stick].m_count; - if (touchpad < touchpadCount) { - HALJoystickTouchpad tp = m_joystickTouchpads[stick].m_touchpads[touchpad]; - if (finger < tp.m_count) { - return new TouchpadFinger( - tp.m_fingers[finger].m_down, tp.m_fingers[finger].m_x, tp.m_fingers[finger].m_y); - } - } - } finally { - m_cacheDataMutex.unlock(); - } - - reportJoystickWarning( - stick, - "Joystick touchpad finger " - + finger - + " on touchpad " - + touchpad - + " on port " - + stick - + " not available"); - return new TouchpadFinger(false, 0.0f, 0.0f); - } - - /** - * Get whether a touchpad finger on the joystick is available. - * - * @param stick The joystick to read. - * @param touchpad The touchpad to read. - * @param finger The finger to read. - * @return whether the touchpad finger is available. - */ - public static boolean getStickTouchpadFingerAvailable(int stick, int touchpad, int finger) { - if (stick < 0 || stick >= kJoystickPorts) { - throw new IllegalArgumentException("Joystick index is out of range, should be 0-5"); - } - if (touchpad < 0 || touchpad >= DriverStationJNI.MAX_JOYSTICK_TOUCHPADS) { - throw new IllegalArgumentException("Joystick touchpad is out of range"); - } - if (finger < 0 || finger >= DriverStationJNI.MAX_JOYSTICK_TOUCHPAD_FINGERS) { - throw new IllegalArgumentException("Joystick touchpad finger is out of range"); - } - - int touchpadCount; - m_cacheDataMutex.lock(); - try { - touchpadCount = m_joystickTouchpads[stick].m_count; - if (touchpad < touchpadCount) { - HALJoystickTouchpad tp = m_joystickTouchpads[stick].m_touchpads[touchpad]; - if (finger < tp.m_count) { - return true; - } - } - } finally { - m_cacheDataMutex.unlock(); - } - - return false; - } - - /** - * Get the value of the axis on a joystick if available. This depends on the mapping of the - * joystick connected to the specified port. - * - * @param stick The joystick to read. - * @param axis The analog axis value to read from the joystick. - * @return The value of the axis on the joystick, or 0 if the axis is not available. - */ - public static OptionalDouble getStickAxisIfAvailable(int stick, int axis) { - if (stick < 0 || stick >= kJoystickPorts) { - throw new IllegalArgumentException("Joystick index is out of range, should be 0-5"); - } - if (axis < 0 || axis >= DriverStationJNI.MAX_JOYSTICK_AXES) { - throw new IllegalArgumentException("Joystick axis is out of range"); - } - - int mask = 1 << axis; - - m_cacheDataMutex.lock(); - try { - if ((m_joystickAxes[stick].m_available & mask) != 0) { - return OptionalDouble.of(m_joystickAxes[stick].m_axes[axis]); - } - } finally { - m_cacheDataMutex.unlock(); - } - - return OptionalDouble.empty(); - } - - /** - * Get the state of a POV on the joystick. - * - * @param stick The joystick to read. - * @param pov The POV to read. - * @return the angle of the POV. - */ - public static POVDirection getStickPOV(int stick, int pov) { - if (stick < 0 || stick >= kJoystickPorts) { - throw new IllegalArgumentException("Joystick index is out of range, should be 0-5"); - } - if (pov < 0 || pov >= DriverStationJNI.MAX_JOYSTICK_POVS) { - throw new IllegalArgumentException("Joystick POV is out of range"); - } - - int mask = 1 << pov; - - m_cacheDataMutex.lock(); - try { - if ((m_joystickPOVs[stick].m_available & mask) != 0) { - return POVDirection.of(m_joystickPOVs[stick].m_povs[pov]); - } - } finally { - m_cacheDataMutex.unlock(); - } - - reportJoystickWarning(stick, "Joystick POV " + pov + " on port " + stick + " not available"); - return POVDirection.CENTER; - } - - /** - * The state of the buttons on the joystick. - * - * @param stick The joystick to read. - * @return The state of the buttons on the joystick. - */ - public static long getStickButtons(final int stick) { - if (stick < 0 || stick >= kJoystickPorts) { - throw new IllegalArgumentException("Joystick index is out of range, should be 0-5"); - } - - m_cacheDataMutex.lock(); - try { - return m_joystickButtons[stick].m_buttons; - } finally { - m_cacheDataMutex.unlock(); - } - } - - /** - * Gets the maximum index of axes on a given joystick port. - * - * @param stick The joystick port number - * @return The maximum index of axes on the indicated joystick - */ - public static int getStickAxesMaximumIndex(int stick) { - return availableToCount(getStickAxesAvailable(stick)); - } - - /** - * Returns the available bitmask of axes on a given joystick port. - * - * @param stick The joystick port number - * @return The number of axes available on the indicated joystick - */ - public static int getStickAxesAvailable(int stick) { - if (stick < 0 || stick >= kJoystickPorts) { - throw new IllegalArgumentException("Joystick index is out of range, should be 0-5"); - } - - m_cacheDataMutex.lock(); - try { - return m_joystickAxes[stick].m_available; - } finally { - m_cacheDataMutex.unlock(); - } - } - - /** - * Gets the maximum index of povs on a given joystick port. - * - * @param stick The joystick port number - * @return The maximum index of povs on the indicated joystick - */ - public static int getStickPOVsMaximumIndex(int stick) { - return availableToCount(getStickPOVsAvailable(stick)); - } - - /** - * Returns the available bitmask of povs on a given joystick port. - * - * @param stick The joystick port number - * @return The number of povs available on the indicated joystick - */ - public static int getStickPOVsAvailable(int stick) { - if (stick < 0 || stick >= kJoystickPorts) { - throw new IllegalArgumentException("Joystick index is out of range, should be 0-5"); - } - - m_cacheDataMutex.lock(); - try { - return m_joystickPOVs[stick].m_available; - } finally { - m_cacheDataMutex.unlock(); - } - } - - /** - * Gets the maximum index of buttons on a given joystick port. - * - * @param stick The joystick port number - * @return The maximum index of buttons on the indicated joystick - */ - public static int getStickButtonsMaximumIndex(int stick) { - return availableToCount(getStickButtonsAvailable(stick)); - } - - /** - * Gets the bitmask of buttons available. - * - * @param stick The joystick port number - * @return The buttons available on the indicated joystick - */ - public static long getStickButtonsAvailable(int stick) { - if (stick < 0 || stick >= kJoystickPorts) { - throw new IllegalArgumentException("Joystick index is out of range, should be 0-5"); - } - - m_cacheDataMutex.lock(); - try { - return m_joystickButtons[stick].m_available; - } finally { - m_cacheDataMutex.unlock(); - } - } - - /** - * Gets the value of isGamepad on a joystick. - * - * @param stick The joystick port number - * @return A boolean that returns the value of isGamepad - */ - public static boolean getJoystickIsGamepad(int stick) { - if (stick < 0 || stick >= kJoystickPorts) { - throw new IllegalArgumentException("Joystick index is out of range, should be 0-5"); - } - - return DriverStationJNI.getJoystickIsGamepad((byte) stick) == 1; - } - - /** - * Gets the value of type on a gamepad. - * - * @param stick The joystick port number - * @return The value of type - */ - public static int getJoystickGamepadType(int stick) { - if (stick < 0 || stick >= kJoystickPorts) { - throw new IllegalArgumentException("Joystick index is out of range, should be 0-5"); - } - - return DriverStationJNI.getJoystickGamepadType((byte) stick); - } - - /** - * Gets the value of supported outputs on a joystick. - * - * @param stick The joystick port number - * @return The value of supported outputs - */ - public static int getJoystickSupportedOutputs(int stick) { - if (stick < 0 || stick >= kJoystickPorts) { - throw new IllegalArgumentException("Joystick index is out of range, should be 0-5"); - } - - return DriverStationJNI.getJoystickSupportedOutputs((byte) stick); - } - - /** - * Gets the name of the joystick at a port. - * - * @param stick The joystick port number - * @return The value of name - */ - public static String getJoystickName(int stick) { - if (stick < 0 || stick >= kJoystickPorts) { - throw new IllegalArgumentException("Joystick index is out of range, should be 0-5"); - } - - return DriverStationJNI.getJoystickName((byte) stick); - } - - /** - * Returns if a joystick is connected to the Driver Station. - * - *

This makes a best effort guess by looking at the reported number of axis, buttons, and POVs - * attached. - * - * @param stick The joystick port number - * @return true if a joystick is connected - */ - public static boolean isJoystickConnected(int stick) { - return getStickAxesAvailable(stick) != 0 - || getStickButtonsAvailable(stick) != 0 - || getStickPOVsAvailable(stick) != 0; - } - - /** - * Gets a value indicating whether the Driver Station requires the robot to be enabled. - * - * @return True if the robot is enabled, false otherwise. - */ - public static boolean isEnabled() { - m_cacheDataMutex.lock(); - try { - return m_controlWord.isEnabled() && m_controlWord.isDSAttached(); - } finally { - m_cacheDataMutex.unlock(); - } - } - - /** - * Gets a value indicating whether the Driver Station requires the robot to be disabled. - * - * @return True if the robot should be disabled, false otherwise. - */ - public static boolean isDisabled() { - return !isEnabled(); - } - - /** - * Gets a value indicating whether the Robot is e-stopped. - * - * @return True if the robot is e-stopped, false otherwise. - */ - public static boolean isEStopped() { - m_cacheDataMutex.lock(); - try { - return m_controlWord.isEStopped(); - } finally { - m_cacheDataMutex.unlock(); - } - } - - /** - * Gets the current robot mode. - * - *

Note that this does not indicate whether the robot is enabled or disabled. - * - * @return robot mode - */ - public static RobotMode getRobotMode() { - m_cacheDataMutex.lock(); - try { - return m_controlWord.getRobotMode(); - } finally { - m_cacheDataMutex.unlock(); - } - } - - /** - * Gets a value indicating whether the Driver Station requires the robot to be running in - * autonomous mode. - * - * @return True if autonomous mode should be enabled, false otherwise. - */ - public static boolean isAutonomous() { - m_cacheDataMutex.lock(); - try { - return m_controlWord.isAutonomous(); - } finally { - m_cacheDataMutex.unlock(); - } - } - - /** - * Gets a value indicating whether the Driver Station requires the robot to be running in - * autonomous mode and enabled. - * - * @return True if autonomous should be set and the robot should be enabled. - */ - public static boolean isAutonomousEnabled() { - m_cacheDataMutex.lock(); - try { - return m_controlWord.isAutonomousEnabled(); - } finally { - m_cacheDataMutex.unlock(); - } - } - - /** - * Gets a value indicating whether the Driver Station requires the robot to be running in - * operator-controlled mode. - * - * @return True if operator-controlled mode should be enabled, false otherwise. - */ - public static boolean isTeleop() { - return m_controlWord.isTeleop(); - } - - /** - * Gets a value indicating whether the Driver Station requires the robot to be running in - * operator-controller mode and enabled. - * - * @return True if operator-controlled mode should be set and the robot should be enabled. - */ - public static boolean isTeleopEnabled() { - m_cacheDataMutex.lock(); - try { - return m_controlWord.isTeleopEnabled(); - } finally { - m_cacheDataMutex.unlock(); - } - } - - /** - * Gets a value indicating whether the Driver Station requires the robot to be running in Test - * mode. - * - * @return True if test mode should be enabled, false otherwise. - */ - public static boolean isTest() { - m_cacheDataMutex.lock(); - try { - return m_controlWord.isTest(); - } finally { - m_cacheDataMutex.unlock(); - } - } - - /** - * Gets a value indicating whether the Driver Station requires the robot to be running in Test - * mode and enabled. - * - * @return True if test mode should be set and the robot should be enabled. - */ - public static boolean isTestEnabled() { - m_cacheDataMutex.lock(); - try { - return m_controlWord.isTestEnabled(); - } finally { - m_cacheDataMutex.unlock(); - } - } - - private static int convertColorToInt(Color color) { - if (color == null) { - return -1; - } - return (((int) (color.red * 255) & 0xff) << 16) - | (((int) (color.green * 255) & 0xff) << 8) - | ((int) (color.blue * 255) & 0xff); - } - - /** - * Adds an operating mode option. It's necessary to call publishOpModes() to make the added modes - * visible to the driver station. - * - * @param mode robot mode - * @param name name of the operating mode - * @param group group of the operating mode - * @param description description of the operating mode - * @param textColor text color, or null for default - * @param backgroundColor background color, or null for default - * @return unique ID used to later identify the operating mode - * @throws IllegalArgumentException if name is empty or an operating mode with the same robot mode - * and name already exists - */ - @SuppressWarnings("PMD.UseStringBufferForStringAppends") - public static long addOpMode( - RobotMode mode, - String name, - String group, - String description, - Color textColor, - Color backgroundColor) { - if (name.isBlank()) { - throw new IllegalArgumentException("OpMode name must be non-blank"); - } - // find unique ID - m_opModesMutex.lock(); - try { - String nameCopy = name; - for (; ; ) { - long id = OpModeOption.makeId(mode, nameCopy.hashCode()); - OpModeOption existing = m_opModes.get(id); - if (existing == null) { - m_opModes.put( - id, - new OpModeOption( - id, - name, - group, - description, - convertColorToInt(textColor), - convertColorToInt(backgroundColor))); - return id; - } - if (existing.getMode() == mode && existing.name.equals(name)) { - // already exists - throw new IllegalArgumentException("OpMode " + name + " already exists for mode " + mode); - } - // collision, try again with space appended - nameCopy += ' '; - } - } finally { - m_opModesMutex.unlock(); - } - } - - /** - * Adds an operating mode option. It's necessary to call publishOpModes() to make the added modes - * visible to the driver station. - * - * @param mode robot mode - * @param name name of the operating mode - * @param group group of the operating mode - * @param description description of the operating mode - * @return unique ID used to later identify the operating mode - * @throws IllegalArgumentException if name is empty or an operating mode with the same name - * already exists - */ - public static long addOpMode(RobotMode mode, String name, String group, String description) { - return addOpMode(mode, name, group, description, null, null); - } - - /** - * Adds an operating mode option. It's necessary to call publishOpModes() to make the added modes - * visible to the driver station. - * - * @param mode robot mode - * @param name name of the operating mode - * @param group group of the operating mode - * @return unique ID used to later identify the operating mode - * @throws IllegalArgumentException if name is empty or an operating mode with the same name - * already exists - */ - public static long addOpMode(RobotMode mode, String name, String group) { - return addOpMode(mode, name, group, ""); - } - - /** - * Adds an operating mode option. It's necessary to call publishOpModes() to make the added modes - * visible to the driver station. - * - * @param mode robot mode - * @param name name of the operating mode - * @return unique ID used to later identify the operating mode - * @throws IllegalArgumentException if name is empty or an operating mode with the same name - * already exists - */ - public static long addOpMode(RobotMode mode, String name) { - return addOpMode(mode, name, ""); - } - - /** - * Removes an operating mode option. It's necessary to call publishOpModes() to make the removed - * mode no longer visible to the driver station. - * - * @param mode robot mode - * @param name name of the operating mode - * @return unique ID for the opmode, or 0 if not found - */ - public static long removeOpMode(RobotMode mode, String name) { - if (name.isBlank()) { - return 0; - } - m_opModesMutex.lock(); - try { - // we have to loop over all entries to find the one with the correct name - // because the of the unique ID generation scheme - for (OpModeOption opMode : m_opModes.values()) { - if (opMode.getMode() == mode && opMode.name.equals(name)) { - m_opModes.remove(opMode.id); - return opMode.id; - } - } - } finally { - m_opModesMutex.unlock(); - } - return 0; - } - - /** Publishes the operating mode options to the driver station. */ - public static void publishOpModes() { - m_opModesMutex.lock(); - try { - OpModeOption[] options = new OpModeOption[m_opModes.size()]; - DriverStationJNI.setOpModeOptions(m_opModes.values().toArray(options)); - } finally { - m_opModesMutex.unlock(); - } - } - - /** Clears all operating mode options and publishes an empty list to the driver station. */ - public static void clearOpModes() { - m_opModesMutex.lock(); - try { - m_opModes.clear(); - DriverStationJNI.setOpModeOptions(new OpModeOption[0]); - } finally { - m_opModesMutex.unlock(); - } - } - - /** - * Sets the program starting flag in the DS. This will also allow {@link #getOpModeId()} and - * {@link #getOpMode()} to return values for the selected OpMode in the DS application, if the DS - * is connected by the time this method is called. - * - *

Most users will not need to use this method; the {@link TimedRobot} and {@link OpModeRobot} - * robot framework classes will call it automatically after the main robot class is instantiated. - * However, teams using the commandsv3 library and a custom main robot class need to be careful to - * only call this method after all mechanisms and global trigger bindings are set up. If not, any - * setup performed in the main robot class may be incorrectly bound to the opmode selected in the - * DS if it's connected by the time the robot program boots up. - * - *

This is what changes the DS to showing robot code ready. - * - * @see #getOpMode() - * @see #getOpModeId() - */ - public static void observeUserProgramStarting() { - m_userProgramStarted = true; - DriverStationJNI.observeUserProgramStarting(); - } - - /** - * Gets the operating mode selected on the driver station. Note this does not mean the robot is - * enabled; use isEnabled() for that. In a match, this will indicate the operating mode selected - * for auto before the match starts (i.e., while the robot is disabled in auto mode); after the - * auto period ends, this will change to reflect the operating mode selected for teleop. - * - *

This method always returns {@code 0} while the main robot class is being constructed and - * initialized (more specifically, it returns {@code 0} until {@link - * #observeUserProgramStarting()} is called, which the WPILib framework will automatically call - * during {@link TimedRobot#startCompetition()} and {@link OpModeRobot#startCompetition()}). - * - * @return the unique ID provided by the addOpMode() function; may return 0 or a unique ID not - * added, so callers should be prepared to handle that case - */ - public static long getOpModeId() { - if (!m_userProgramStarted) { - return 0; - } - - m_cacheDataMutex.lock(); - try { - return m_controlWord.getOpModeId(); - } finally { - m_cacheDataMutex.unlock(); - } - } - - /** - * Gets the operating mode selected on the driver station. Note this does not mean the robot is - * enabled; use isEnabled() for that. In a match, this will indicate the operating mode selected - * for auto before the match starts (i.e., while the robot is disabled in auto mode); after the - * auto period ends, this will change to reflect the operating mode selected for teleop. - * - *

This method always returns an empty string {@code ""} while the main robot class is being - * constructed and initialized (more specifically, it returns {@code ""} until {@link - * #observeUserProgramStarting()} is called, which the WPILib framework will automatically call - * during {@link TimedRobot#startCompetition()} and {@link OpModeRobot#startCompetition()}). - * - * @return Operating mode string; may return a string not in the list of options, so callers - * should be prepared to handle that case - */ - public static String getOpMode() { - if (!m_userProgramStarted) { - return ""; - } - - m_cacheDataMutex.lock(); - try { - return m_opMode; - } finally { - m_cacheDataMutex.unlock(); - } - } - - /** - * Check to see if the selected operating mode is a particular value. Note this does not mean the - * robot is enabled; use isEnabled() for that. - * - * @param id operating mode unique ID - * @return True if that mode is the current mode - */ - public static boolean isOpMode(long id) { - return getOpModeId() == id; - } - - /** - * Check to see if the selected operating mode is a particular value. Note this does not mean the - * robot is enabled; use isEnabled() for that. - * - * @param mode operating mode - * @return True if that mode is the current mode - */ - public static boolean isOpMode(String mode) { - return getOpMode().equals(mode); - } - - /** - * Gets a value indicating whether the Driver Station is attached. - * - * @return True if Driver Station is attached, false otherwise. - */ - public static boolean isDSAttached() { - m_cacheDataMutex.lock(); - try { - return m_controlWord.isDSAttached(); - } finally { - m_cacheDataMutex.unlock(); - } - } - - /** - * Gets if the driver station attached to a Field Management System. - * - * @return true if the robot is competing on a field being controlled by a Field Management System - */ - public static boolean isFMSAttached() { - m_cacheDataMutex.lock(); - try { - return m_controlWord.isFMSAttached(); - } finally { - m_cacheDataMutex.unlock(); - } - } - - /** - * Get the game specific message from the FMS. - * - *

If the FMS is not connected, it is set from the game data setting on the driver station. - * - * @return the game specific message - */ - public static Optional getGameData() { - m_cacheDataMutex.lock(); - try { - if (m_gameData == null || m_gameData.isEmpty()) { - return Optional.empty(); - } - return Optional.of(m_gameData); - } finally { - m_cacheDataMutex.unlock(); - } - } - - /** - * Get the event name from the FMS. - * - * @return the event name - */ - public static String getEventName() { - m_cacheDataMutex.lock(); - try { - return m_matchInfo.eventName; - } finally { - m_cacheDataMutex.unlock(); - } - } - - /** - * Get the match type from the FMS. - * - * @return the match type - */ - public static MatchType getMatchType() { - int matchType; - m_cacheDataMutex.lock(); - try { - matchType = m_matchInfo.matchType; - } finally { - m_cacheDataMutex.unlock(); - } - return switch (matchType) { - case 1 -> MatchType.PRACTICE; - case 2 -> MatchType.QUALIFICATION; - case 3 -> MatchType.ELIMINATION; - default -> MatchType.NONE; - }; - } - - /** - * Get the match number from the FMS. - * - * @return the match number - */ - public static int getMatchNumber() { - m_cacheDataMutex.lock(); - try { - return m_matchInfo.matchNumber; - } finally { - m_cacheDataMutex.unlock(); - } - } - - /** - * Get the replay number from the FMS. - * - * @return the replay number - */ - public static int getReplayNumber() { - m_cacheDataMutex.lock(); - try { - return m_matchInfo.replayNumber; - } finally { - m_cacheDataMutex.unlock(); - } - } - - private static Map> m_allianceMap = - Map.of( - AllianceStationID.UNKNOWN, Optional.empty(), - AllianceStationID.RED_1, Optional.of(Alliance.RED), - AllianceStationID.RED_2, Optional.of(Alliance.RED), - AllianceStationID.RED_3, Optional.of(Alliance.RED), - AllianceStationID.BLUE_1, Optional.of(Alliance.BLUE), - AllianceStationID.BLUE_2, Optional.of(Alliance.BLUE), - AllianceStationID.BLUE_3, Optional.of(Alliance.BLUE)); - - private static Map m_stationMap = - Map.of( - AllianceStationID.UNKNOWN, OptionalInt.empty(), - AllianceStationID.RED_1, OptionalInt.of(1), - AllianceStationID.RED_2, OptionalInt.of(2), - AllianceStationID.RED_3, OptionalInt.of(3), - AllianceStationID.BLUE_1, OptionalInt.of(1), - AllianceStationID.BLUE_2, OptionalInt.of(2), - AllianceStationID.BLUE_3, OptionalInt.of(3)); - - /** - * Get the current alliance from the FMS. - * - *

If the FMS is not connected, it is set from the team alliance setting on the driver station. - * - * @return The alliance (red or blue) or an empty optional if the alliance is invalid - */ - public static Optional getAlliance() { - AllianceStationID allianceStationID = DriverStationJNI.getAllianceStation(); - if (allianceStationID == null) { - allianceStationID = AllianceStationID.UNKNOWN; - } - - return m_allianceMap.get(allianceStationID); - } - - /** - * Gets the location of the team's driver station controls from the FMS. - * - *

If the FMS is not connected, it is set from the team alliance setting on the driver station. - * - * @return the location of the team's driver station controls: 1, 2, or 3 - */ - public static OptionalInt getLocation() { - AllianceStationID allianceStationID = DriverStationJNI.getAllianceStation(); - if (allianceStationID == null) { - allianceStationID = AllianceStationID.UNKNOWN; - } - - return m_stationMap.get(allianceStationID); - } - - /** - * Gets the raw alliance station of the teams driver station. - * - *

This returns the raw low level value. Prefer getLocation or getAlliance unless necessary for - * performance. - * - * @return The raw alliance station id. - */ - public static AllianceStationID getRawAllianceStation() { - return DriverStationJNI.getAllianceStation(); - } - - /** - * Return the approximate match time. The FMS does not send an official match time to the robots, - * but does send an approximate match time. The value will count down the time remaining in the - * current period (auto or teleop). Warning: This is not an official time (so it cannot be used to - * dispute ref calls or guarantee that a function will trigger before the match ends). - * - *

When connected to the real field, this number only changes in full integer increments, and - * always counts down. - * - *

When the DS is in practice mode, this number is a floating point number, and counts down. - * - *

When the DS is in teleop or autonomous mode, this number returns -1.0. - * - *

Simulation matches DS behavior without an FMS connected. - * - * @return Time remaining in current match period (auto or teleop) in seconds - */ - public static double getMatchTime() { - return DriverStationJNI.getMatchTime(); - } - - /** - * Allows the user to specify whether they want joystick connection warnings to be printed to the - * console. This setting is ignored when the FMS is connected -- warnings will always be on in - * that scenario. - * - * @param silence Whether warning messages should be silenced. - */ - public static void silenceJoystickConnectionWarning(boolean silence) { - m_silenceJoystickWarning = silence; - } - - /** - * Returns whether joystick connection warnings are silenced. This will always return false when - * connected to the FMS. - * - * @return Whether joystick connection warnings are silenced. - */ - public static boolean isJoystickConnectionWarningSilenced() { - return !isFMSAttached() && m_silenceJoystickWarning; - } - - /** - * Refresh the passed in control word to contain the current control word cache. - * - * @param word Word to refresh. - */ - public static void refreshControlWordFromCache(ControlWord word) { - m_cacheDataMutex.lock(); - try { - word.update(m_controlWord); - } finally { - m_cacheDataMutex.unlock(); - } - } - - /** - * Copy data from the DS task for the user. If no new data exists, it will just be returned, - * otherwise the data will be copied from the DS polling loop. - */ - public static void refreshData() { - DriverStationJNI.refreshDSData(); - - // Get the status of all the joysticks - for (byte stick = 0; stick < kJoystickPorts; stick++) { - DriverStationJNI.getAllJoystickData( - stick, - m_joystickAxesCache[stick].m_axes, - m_joystickAxesRawCache[stick].m_axes, - m_joystickPOVsCache[stick].m_povs, - m_touchpadFingersCache, - m_metadataCache); - m_joystickAxesCache[stick].m_available = (int) m_metadataCache[0]; - m_joystickAxesRawCache[stick].m_available = (int) m_metadataCache[0]; - m_joystickPOVsCache[stick].m_available = (int) m_metadataCache[1]; - m_joystickButtonsCache[stick].m_available = m_metadataCache[2]; - m_joystickButtonsCache[stick].m_buttons = m_metadataCache[3]; - m_joystickTouchpadsCache[stick].m_count = (int) m_metadataCache[4]; - for (int i = 0; i < m_joystickTouchpadsCache[stick].m_count; i++) { - long metadata = m_metadataCache[5 + i]; - m_joystickTouchpadsCache[stick].m_touchpads[i].m_fingers[0].m_down = (metadata & 0x1) != 0; - m_joystickTouchpadsCache[stick].m_touchpads[i].m_fingers[1].m_down = (metadata & 0x2) != 0; - m_joystickTouchpadsCache[stick].m_touchpads[i].m_count = (int) (metadata >> 2 & 0x3); - for (int j = 0; j < m_joystickTouchpadsCache[stick].m_touchpads[i].m_count; j++) { - m_joystickTouchpadsCache[stick].m_touchpads[i].m_fingers[j].m_x = - m_touchpadFingersCache[i * 4 + j * 2 + 0]; - m_joystickTouchpadsCache[stick].m_touchpads[i].m_fingers[j].m_y = - m_touchpadFingersCache[i * 4 + j * 2 + 1]; - } - } - } - - DriverStationJNI.getMatchInfo(m_matchInfoCache); - - // This is a pass through, so if it hasn't changed, it doesn't - // reallocate - m_gameDataCache = DriverStationJNI.getGameData(m_gameDataCache); - - DriverStationJNI.getControlWord(m_controlWordCache); - - m_opModeCache = opModeToString(m_controlWordCache.getOpModeId()); - - DataLogSender dataLogSender; - // lock joystick mutex to swap cache data - m_cacheDataMutex.lock(); - try { - for (int i = 0; i < kJoystickPorts; i++) { - // If buttons weren't pressed and are now, set flags in m_buttonsPressed - m_joystickButtonsPressed[i] |= - ~m_joystickButtons[i].m_buttons & m_joystickButtonsCache[i].m_buttons; - - // If buttons were pressed and aren't now, set flags in m_buttonsReleased - m_joystickButtonsReleased[i] |= - m_joystickButtons[i].m_buttons & ~m_joystickButtonsCache[i].m_buttons; - } - - // move cache to actual data - HALJoystickAxes[] currentAxes = m_joystickAxes; - m_joystickAxes = m_joystickAxesCache; - m_joystickAxesCache = currentAxes; - - HALJoystickAxesRaw[] currentAxesRaw = m_joystickAxesRaw; - m_joystickAxesRaw = m_joystickAxesRawCache; - m_joystickAxesRawCache = currentAxesRaw; - - HALJoystickButtons[] currentButtons = m_joystickButtons; - m_joystickButtons = m_joystickButtonsCache; - m_joystickButtonsCache = currentButtons; - - HALJoystickPOVs[] currentPOVs = m_joystickPOVs; - m_joystickPOVs = m_joystickPOVsCache; - m_joystickPOVsCache = currentPOVs; - - HALJoystickTouchpads[] currentTouchpads = m_joystickTouchpads; - m_joystickTouchpads = m_joystickTouchpadsCache; - m_joystickTouchpadsCache = currentTouchpads; - - MatchInfoData currentInfo = m_matchInfo; - m_matchInfo = m_matchInfoCache; - m_matchInfoCache = currentInfo; - - m_gameData = m_gameDataCache; - - ControlWord currentWord = m_controlWord; - m_controlWord = m_controlWordCache; - m_controlWordCache = currentWord; - - String currentOpMode = m_opMode; - m_opMode = m_opModeCache; - m_opModeCache = currentOpMode; - - dataLogSender = m_dataLogSender; - } finally { - m_cacheDataMutex.unlock(); - } - - m_refreshEvents.wakeup(); - - m_matchDataSender.sendMatchData(); - if (dataLogSender != null) { - dataLogSender.send(WPIUtilJNI.now()); - } - } - - /** - * Registers the given handle for DS data refresh notifications. - * - * @param handle The event handle. - */ - public static void provideRefreshedDataEventHandle(int handle) { - m_refreshEvents.add(handle); - } - - /** - * Unregisters the given handle from DS data refresh notifications. - * - * @param handle The event handle. - */ - public static void removeRefreshedDataEventHandle(int handle) { - m_refreshEvents.remove(handle); - } - - /** - * Reports errors related to joystick availability. Throttles the errors so that they don't - * overwhelm the DS. - * - * @param stick The joystick port. - * @param message The message to report if the joystick is connected. - */ - private static void reportJoystickWarning(int stick, String message) { - if (isFMSAttached() || !m_silenceJoystickWarning) { - double currentTime = Timer.getTimestamp(); - if (currentTime > m_nextMessageTime) { - if (isJoystickConnected(stick)) { - reportWarning(message, false); - } else { - reportWarning( - "Joystick on port " + stick + " not available, check if controller is plugged in", - false); - } - m_nextMessageTime = currentTime + JOYSTICK_UNPLUGGED_MESSAGE_INTERVAL; - } - } - } - - /** - * Starts logging DriverStation data to data log. Repeated calls are ignored. - * - * @param log data log - * @param logJoysticks if true, log joystick data - */ - @SuppressWarnings("PMD.NonThreadSafeSingleton") - public static void startDataLog(DataLog log, boolean logJoysticks) { - m_cacheDataMutex.lock(); - try { - if (m_dataLogSender == null) { - m_dataLogSender = new DataLogSender(log, logJoysticks, WPIUtilJNI.now()); - } - } finally { - m_cacheDataMutex.unlock(); - } - } - /** * Starts logging DriverStation data to data log, including joystick data. Repeated calls are * ignored. @@ -1974,6 +18,34 @@ public final class DriverStation { * @param log data log */ public static void startDataLog(DataLog log) { - startDataLog(log, true); + DriverStationBackend.startDataLog(log); + } + + /** + * Starts logging DriverStation data to data log. Repeated calls are ignored. + * + * @param log data log + * @param logJoysticks if true, log joystick data + */ + public static void startDataLog(DataLog log, boolean logJoysticks) { + DriverStationBackend.startDataLog(log, logJoysticks); + } + + /** + * Registers the given handle for DS data refresh notifications. + * + * @param handle The event handle. + */ + public static void provideRefreshedDataEventHandle(int handle) { + DriverStationBackend.provideRefreshedDataEventHandle(handle); + } + + /** + * Unregisters the given handle from DS data refresh notifications. + * + * @param handle The event handle. + */ + public static void removeRefreshedDataEventHandle(int handle) { + DriverStationBackend.removeRefreshedDataEventHandle(handle); } } diff --git a/wpilibj/src/main/java/org/wpilib/driverstation/DriverStationErrors.java b/wpilibj/src/main/java/org/wpilib/driverstation/DriverStationErrors.java new file mode 100644 index 0000000000..2ea24ce1ad --- /dev/null +++ b/wpilibj/src/main/java/org/wpilib/driverstation/DriverStationErrors.java @@ -0,0 +1,52 @@ +// 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.driverstation; + +import org.wpilib.driverstation.internal.DriverStationBackend; + +/** Provides access to error and warning reporting functionality to the Driver Station. */ +public final class DriverStationErrors { + private DriverStationErrors() {} + + /** + * Report error to Driver Station. Optionally appends Stack trace to error message. + * + * @param error The error to report. + * @param printTrace If true, append stack trace to error string + */ + public static void reportError(String error, boolean printTrace) { + DriverStationBackend.reportError(error, printTrace); + } + + /** + * Report error to Driver Station. Appends provided stack trace to error message. + * + * @param error The error to report. + * @param stackTrace The stack trace to append + */ + public static void reportError(String error, StackTraceElement[] stackTrace) { + DriverStationBackend.reportError(error, stackTrace); + } + + /** + * Report warning to Driver Station. Optionally appends Stack trace to warning message. + * + * @param warning The warning to report. + * @param printTrace If true, append stack trace to warning string + */ + public static void reportWarning(String warning, boolean printTrace) { + DriverStationBackend.reportWarning(warning, printTrace); + } + + /** + * Report warning to Driver Station. Appends provided stack trace to warning message. + * + * @param warning The warning to report. + * @param stackTrace The stack trace to append + */ + public static void reportWarning(String warning, StackTraceElement[] stackTrace) { + DriverStationBackend.reportWarning(warning, stackTrace); + } +} diff --git a/wpilibj/src/main/java/org/wpilib/driverstation/Gamepad.java b/wpilibj/src/main/java/org/wpilib/driverstation/Gamepad.java index 82d739ebef..10c32e3d26 100644 --- a/wpilibj/src/main/java/org/wpilib/driverstation/Gamepad.java +++ b/wpilibj/src/main/java/org/wpilib/driverstation/Gamepad.java @@ -4,6 +4,7 @@ package org.wpilib.driverstation; +import org.wpilib.driverstation.internal.DriverStationBackend; import org.wpilib.event.BooleanEvent; import org.wpilib.event.EventLoop; import org.wpilib.hardware.hal.HAL; @@ -1334,11 +1335,11 @@ public class Gamepad extends GenericHID implements Sendable { } private double getAxisForSendable(Axis axis) { - return DriverStation.getStickAxisIfAvailable(getPort(), axis.value).orElse(0.0); + return DriverStationBackend.getStickAxisIfAvailable(getPort(), axis.value).orElse(0.0); } private boolean getButtonForSendable(Button button) { - return DriverStation.getStickButtonIfAvailable(getPort(), button.value).orElse(false); + return DriverStationBackend.getStickButtonIfAvailable(getPort(), button.value).orElse(false); } @Override diff --git a/wpilibj/src/main/java/org/wpilib/driverstation/GenericHID.java b/wpilibj/src/main/java/org/wpilib/driverstation/GenericHID.java index 784ce697d3..814386b671 100644 --- a/wpilibj/src/main/java/org/wpilib/driverstation/GenericHID.java +++ b/wpilibj/src/main/java/org/wpilib/driverstation/GenericHID.java @@ -7,8 +7,7 @@ package org.wpilib.driverstation; import java.util.EnumSet; import java.util.HashMap; import java.util.Map; -import org.wpilib.driverstation.DriverStation.POVDirection; -import org.wpilib.driverstation.DriverStation.TouchpadFinger; +import org.wpilib.driverstation.internal.DriverStationBackend; import org.wpilib.event.BooleanEvent; import org.wpilib.event.EventLoop; import org.wpilib.hardware.hal.DriverStationJNI; @@ -150,7 +149,7 @@ public class GenericHID { * @return The state of the button. */ public boolean getRawButton(int button) { - return DriverStation.getStickButton(m_port, (byte) button); + return DriverStationBackend.getStickButton(m_port, (byte) button); } /** @@ -164,7 +163,7 @@ public class GenericHID { * @return Whether the button was pressed since the last check. */ public boolean getRawButtonPressed(int button) { - return DriverStation.getStickButtonPressed(m_port, (byte) button); + return DriverStationBackend.getStickButtonPressed(m_port, (byte) button); } /** @@ -178,7 +177,7 @@ public class GenericHID { * @return Whether the button was released since the last check. */ public boolean getRawButtonReleased(int button) { - return DriverStation.getStickButtonReleased(m_port, button); + return DriverStationBackend.getStickButtonReleased(m_port, button); } /** @@ -202,7 +201,7 @@ public class GenericHID { * @return The value of the axis. */ public double getRawAxis(int axis) { - return DriverStation.getStickAxis(m_port, axis); + return DriverStationBackend.getStickAxis(m_port, axis); } /** @@ -212,7 +211,7 @@ public class GenericHID { * @return the angle of the POV. */ public POVDirection getPOV(int pov) { - return DriverStation.getStickPOV(m_port, pov); + return DriverStationBackend.getStickPOV(m_port, pov); } /** @@ -394,7 +393,7 @@ public class GenericHID { * @return the maximum axis index for the joystick */ public int getAxesMaximumIndex() { - return DriverStation.getStickAxesMaximumIndex(m_port); + return DriverStationBackend.getStickAxesMaximumIndex(m_port); } /** @@ -403,7 +402,7 @@ public class GenericHID { * @return the number of axis for the current HID */ public int getAxesAvailable() { - return DriverStation.getStickAxesAvailable(m_port); + return DriverStationBackend.getStickAxesAvailable(m_port); } /** @@ -412,7 +411,7 @@ public class GenericHID { * @return the maximum POV index for the joystick */ public int getPOVsMaximumIndex() { - return DriverStation.getStickPOVsMaximumIndex(m_port); + return DriverStationBackend.getStickPOVsMaximumIndex(m_port); } /** @@ -421,7 +420,7 @@ public class GenericHID { * @return the number of POVs for the current HID */ public int getPOVsAvailable() { - return DriverStation.getStickPOVsAvailable(m_port); + return DriverStationBackend.getStickPOVsAvailable(m_port); } /** @@ -430,7 +429,7 @@ public class GenericHID { * @return the maximum button index for the joystick */ public int getButtonsMaximumIndex() { - return DriverStation.getStickButtonsMaximumIndex(m_port); + return DriverStationBackend.getStickButtonsMaximumIndex(m_port); } /** @@ -439,7 +438,7 @@ public class GenericHID { * @return the number of buttons for the current HID */ public long getButtonsAvailable() { - return DriverStation.getStickButtonsAvailable(m_port); + return DriverStationBackend.getStickButtonsAvailable(m_port); } /** @@ -448,7 +447,7 @@ public class GenericHID { * @return true if the HID is connected */ public boolean isConnected() { - return DriverStation.isJoystickConnected(m_port); + return DriverStationBackend.isJoystickConnected(m_port); } /** @@ -457,7 +456,7 @@ public class GenericHID { * @return the type of the HID. */ public HIDType getGamepadType() { - return HIDType.of(DriverStation.getJoystickGamepadType(m_port)); + return HIDType.of(DriverStationBackend.getJoystickGamepadType(m_port)); } /** @@ -466,7 +465,7 @@ public class GenericHID { * @return the supported outputs for the HID. */ public EnumSet getSupportedOutputs() { - int supported = DriverStation.getJoystickSupportedOutputs(m_port); + int supported = DriverStationBackend.getJoystickSupportedOutputs(m_port); EnumSet outputs = EnumSet.noneOf(SupportedOutput.class); for (SupportedOutput output : SupportedOutput.values()) { if ((supported & output.getValue()) != 0) { @@ -482,7 +481,7 @@ public class GenericHID { * @return the name of the HID. */ public String getName() { - return DriverStation.getJoystickName(m_port); + return DriverStationBackend.getJoystickName(m_port); } /** @@ -543,7 +542,7 @@ public class GenericHID { * @return true if the touchpad finger is available. */ public boolean getTouchpadFingerAvailable(int touchpad, int finger) { - return DriverStation.getStickTouchpadFingerAvailable(m_port, touchpad, finger); + return DriverStationBackend.getStickTouchpadFingerAvailable(m_port, touchpad, finger); } /** @@ -554,6 +553,6 @@ public class GenericHID { * @return The touchpad finger data. */ public TouchpadFinger getTouchpadFinger(int touchpad, int finger) { - return DriverStation.getStickTouchpadFinger(m_port, touchpad, finger); + return DriverStationBackend.getStickTouchpadFinger(m_port, touchpad, finger); } } diff --git a/wpilibj/src/main/java/org/wpilib/driverstation/MatchState.java b/wpilibj/src/main/java/org/wpilib/driverstation/MatchState.java new file mode 100644 index 0000000000..55ad34ffb1 --- /dev/null +++ b/wpilibj/src/main/java/org/wpilib/driverstation/MatchState.java @@ -0,0 +1,104 @@ +// 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.driverstation; + +import java.util.Optional; +import java.util.OptionalInt; +import org.wpilib.driverstation.internal.DriverStationBackend; + +/** Provides access to match state information from the Driver Station. */ +public final class MatchState { + private MatchState() {} + + /** + * Return the approximate match time. The FMS does not send an official match time to the robots, + * but does send an approximate match time. The value will count down the time remaining in the + * current period (auto or teleop). Warning: This is not an official time (so it cannot be used to + * dispute ref calls or guarantee that a function will trigger before the match ends). + * + *

When connected to the real field, this number only changes in full integer increments, and + * always counts down. + * + *

When the DS is in practice mode, this number is a floating point number, and counts down. + * + *

When the DS is in teleop or autonomous mode, this number returns -1.0. + * + *

Simulation matches DS behavior without an FMS connected. + * + * @return Time remaining in current match period (auto or teleop) in seconds + */ + public static double getMatchTime() { + return DriverStationBackend.getMatchTime(); + } + + /** + * Get the current alliance from the FMS. + * + *

If the FMS is not connected, it is set from the team alliance setting on the driver station. + * + * @return The alliance (red or blue) or an empty optional if the alliance is invalid + */ + public static Optional getAlliance() { + return DriverStationBackend.getAlliance(); + } + + /** + * Gets the location of the team's driver station controls from the FMS. + * + *

If the FMS is not connected, it is set from the team alliance setting on the driver station. + * + * @return the location of the team's driver station controls: 1, 2, or 3 + */ + public static OptionalInt getLocation() { + return DriverStationBackend.getLocation(); + } + + /** + * Get the replay number from the FMS. + * + * @return the replay number + */ + public static int getReplayNumber() { + return DriverStationBackend.getReplayNumber(); + } + + /** + * Get the match number from the FMS. + * + * @return the match number + */ + public static int getMatchNumber() { + return DriverStationBackend.getMatchNumber(); + } + + /** + * Get the match type from the FMS. + * + * @return the match type + */ + public static MatchType getMatchType() { + return DriverStationBackend.getMatchType(); + } + + /** + * Get the event name from the FMS. + * + * @return the event name + */ + public static String getEventName() { + return DriverStationBackend.getEventName(); + } + + /** + * Get the game specific message from the FMS. + * + *

If the FMS is not connected, it is set from the game data setting on the driver station. + * + * @return the game specific message + */ + public static Optional getGameData() { + return DriverStationBackend.getGameData(); + } +} diff --git a/wpilibj/src/main/java/org/wpilib/driverstation/MatchType.java b/wpilibj/src/main/java/org/wpilib/driverstation/MatchType.java new file mode 100644 index 0000000000..498211ffdf --- /dev/null +++ b/wpilibj/src/main/java/org/wpilib/driverstation/MatchType.java @@ -0,0 +1,17 @@ +// 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.driverstation; + +/** The type of robot match that the robot is part of. */ +public enum MatchType { + /** None. */ + NONE, + /** Practice. */ + PRACTICE, + /** Qualification. */ + QUALIFICATION, + /** Elimination. */ + ELIMINATION +} diff --git a/wpilibj/src/main/java/org/wpilib/driverstation/POVDirection.java b/wpilibj/src/main/java/org/wpilib/driverstation/POVDirection.java new file mode 100644 index 0000000000..9487930399 --- /dev/null +++ b/wpilibj/src/main/java/org/wpilib/driverstation/POVDirection.java @@ -0,0 +1,82 @@ +// 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.driverstation; + +import java.util.Optional; +import org.wpilib.math.geometry.Rotation2d; +import org.wpilib.system.Timer; + +/** A controller POV direction. */ +public enum POVDirection { + /** POV center. */ + CENTER(0x00), + /** POV up. */ + UP(0x01), + /** POV up right. */ + UP_RIGHT(0x01 | 0x02), + /** POV right. */ + RIGHT(0x02), + /** POV down right. */ + DOWN_RIGHT(0x02 | 0x04), + /** POV down. */ + DOWN(0x04), + /** POV down left. */ + DOWN_LEFT(0x04 | 0x08), + /** POV left. */ + LEFT(0x08), + /** POV up left. */ + UP_LEFT(0x01 | 0x08); + + private static final double INVALID_POV_VALUE_INTERVAL = 1.0; + private static double s_nextMessageTime; + + /** + * Converts a byte value into a POVDirection enum value. + * + * @param value The byte value to convert. + * @return The corresponding POVDirection enum value. + * @throws IllegalArgumentException If value does not correspond to a POVDirection. + */ + public static POVDirection of(byte value) { + for (var direction : values()) { + if (direction.value == value) { + return direction; + } + } + double currentTime = Timer.getTimestamp(); + if (currentTime > s_nextMessageTime) { + DriverStationErrors.reportError("Invalid POV value " + value + "!", false); + s_nextMessageTime = currentTime + INVALID_POV_VALUE_INTERVAL; + } + return CENTER; + } + + /** The corresponding HAL value. */ + public final byte value; + + POVDirection(int value) { + this.value = (byte) value; + } + + /** + * Gets the angle of a POVDirection. + * + * @return The angle clockwise from straight up, or Optional.empty() if this POVDirection is + * CENTER. + */ + public Optional getAngle() { + return switch (this) { + case CENTER -> Optional.empty(); + case UP -> Optional.of(Rotation2d.fromDegrees(0)); + case UP_RIGHT -> Optional.of(Rotation2d.fromDegrees(45)); + case RIGHT -> Optional.of(Rotation2d.fromDegrees(90)); + case DOWN_RIGHT -> Optional.of(Rotation2d.fromDegrees(135)); + case DOWN -> Optional.of(Rotation2d.fromDegrees(180)); + case DOWN_LEFT -> Optional.of(Rotation2d.fromDegrees(225)); + case LEFT -> Optional.of(Rotation2d.fromDegrees(270)); + case UP_LEFT -> Optional.of(Rotation2d.fromDegrees(315)); + }; + } +} diff --git a/wpilibj/src/main/java/org/wpilib/driverstation/RobotState.java b/wpilibj/src/main/java/org/wpilib/driverstation/RobotState.java new file mode 100644 index 0000000000..142c79ba67 --- /dev/null +++ b/wpilibj/src/main/java/org/wpilib/driverstation/RobotState.java @@ -0,0 +1,270 @@ +// 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.driverstation; + +import org.wpilib.driverstation.internal.DriverStationBackend; +import org.wpilib.hardware.hal.RobotMode; +import org.wpilib.util.Color; + +/** Provides access to robot state information from the Driver Station. */ +public final class RobotState { + private RobotState() {} + + /** + * Gets a value indicating whether the Driver Station requires the robot to be enabled. + * + * @return True if the robot is enabled, false otherwise. + */ + public static boolean isEnabled() { + return DriverStationBackend.isEnabled(); + } + + /** + * Gets a value indicating whether the Driver Station requires the robot to be disabled. + * + * @return True if the robot should be disabled, false otherwise. + */ + public static boolean isDisabled() { + return DriverStationBackend.isDisabled(); + } + + /** + * Gets a value indicating whether the Robot is e-stopped. + * + * @return True if the robot is e-stopped, false otherwise. + */ + public static boolean isEStopped() { + return DriverStationBackend.isEStopped(); + } + + /** + * Gets the current robot mode. + * + *

Note that this does not indicate whether the robot is enabled or disabled. + * + * @return robot mode + */ + public static RobotMode getRobotMode() { + return DriverStationBackend.getRobotMode(); + } + + /** + * Gets a value indicating whether the Driver Station requires the robot to be running in + * autonomous mode. + * + * @return True if autonomous mode should be enabled, false otherwise. + */ + public static boolean isAutonomous() { + return DriverStationBackend.isAutonomous(); + } + + /** + * Gets a value indicating whether the Driver Station requires the robot to be running in + * autonomous mode and enabled. + * + * @return True if autonomous should be set and the robot should be enabled. + */ + public static boolean isAutonomousEnabled() { + return DriverStationBackend.isAutonomousEnabled(); + } + + /** + * Gets a value indicating whether the Driver Station requires the robot to be running in + * operator-controlled mode. + * + * @return True if operator-controlled mode should be enabled, false otherwise. + */ + public static boolean isTeleop() { + return DriverStationBackend.isTeleop(); + } + + /** + * Gets a value indicating whether the Driver Station requires the robot to be running in + * operator-controller mode and enabled. + * + * @return True if operator-controlled mode should be set and the robot should be enabled. + */ + public static boolean isTeleopEnabled() { + return DriverStationBackend.isTeleopEnabled(); + } + + /** + * Gets a value indicating whether the Driver Station requires the robot to be running in Test + * mode. + * + * @return True if test mode should be enabled, false otherwise. + */ + public static boolean isTest() { + return DriverStationBackend.isTest(); + } + + /** + * Gets a value indicating whether the Driver Station requires the robot to be running in Test + * mode and enabled. + * + * @return True if test mode should be set and the robot should be enabled. + */ + public static boolean isTestEnabled() { + return DriverStationBackend.isTestEnabled(); + } + + /** + * Adds an operating mode option. It's necessary to call publishOpModes() to make the added modes + * visible to the driver station. + * + * @param mode robot mode + * @param name name of the operating mode + * @param group group of the operating mode + * @param description description of the operating mode + * @param textColor text color, or null for default + * @param backgroundColor background color, or null for default + * @return unique ID used to later identify the operating mode + * @throws IllegalArgumentException if name is empty or an operating mode with the same robot mode + * and name already exists + */ + public static long addOpMode( + RobotMode mode, + String name, + String group, + String description, + Color textColor, + Color backgroundColor) { + return DriverStationBackend.addOpMode( + mode, name, group, description, textColor, backgroundColor); + } + + /** + * Adds an operating mode option. It's necessary to call publishOpModes() to make the added modes + * visible to the driver station. + * + * @param mode robot mode + * @param name name of the operating mode + * @param group group of the operating mode + * @param description description of the operating mode + * @return unique ID used to later identify the operating mode + * @throws IllegalArgumentException if name is empty or an operating mode with the same name + * already exists + */ + public static long addOpMode(RobotMode mode, String name, String group, String description) { + return DriverStationBackend.addOpMode(mode, name, group, description); + } + + /** + * Adds an operating mode option. It's necessary to call publishOpModes() to make the added modes + * visible to the driver station. + * + * @param mode robot mode + * @param name name of the operating mode + * @param group group of the operating mode + * @return unique ID used to later identify the operating mode + * @throws IllegalArgumentException if name is empty or an operating mode with the same name + * already exists + */ + public static long addOpMode(RobotMode mode, String name, String group) { + return DriverStationBackend.addOpMode(mode, name, group); + } + + /** + * Adds an operating mode option. It's necessary to call publishOpModes() to make the added modes + * visible to the driver station. + * + * @param mode robot mode + * @param name name of the operating mode + * @return unique ID used to later identify the operating mode + * @throws IllegalArgumentException if name is empty or an operating mode with the same name + * already exists + */ + public static long addOpMode(RobotMode mode, String name) { + return DriverStationBackend.addOpMode(mode, name); + } + + /** + * Removes an operating mode option. It's necessary to call publishOpModes() to make the removed + * mode no longer visible to the driver station. + * + * @param mode robot mode + * @param name name of the operating mode + * @return unique ID for the opmode, or 0 if not found + */ + public static long removeOpMode(RobotMode mode, String name) { + return DriverStationBackend.removeOpMode(mode, name); + } + + /** Publishes the operating mode options to the driver station. */ + public static void publishOpModes() { + DriverStationBackend.publishOpModes(); + } + + /** Clears all operating mode options and publishes an empty list to the driver station. */ + public static void clearOpModes() { + DriverStationBackend.clearOpModes(); + } + + /** + * Gets the operating mode selected on the driver station. Note this does not mean the robot is + * enabled; use isEnabled() for that. In a match, this will indicate the operating mode selected + * for auto before the match starts (i.e., while the robot is disabled in auto mode); after the + * auto period ends, this will change to reflect the operating mode selected for teleop. + * + * @return the unique ID provided by the addOpMode() function; may return 0 or a unique ID not + * added, so callers should be prepared to handle that case + */ + public static long getOpModeId() { + return DriverStationBackend.getOpModeId(); + } + + /** + * Gets the operating mode selected on the driver station. Note this does not mean the robot is + * enabled; use isEnabled() for that. In a match, this will indicate the operating mode selected + * for auto before the match starts (i.e., while the robot is disabled in auto mode); after the + * auto period ends, this will change to reflect the operating mode selected for teleop. + * + * @return Operating mode string; may return a string not in the list of options, so callers + * should be prepared to handle that case + */ + public static String getOpMode() { + return DriverStationBackend.getOpMode(); + } + + /** + * Check to see if the selected operating mode is a particular value. Note this does not mean the + * robot is enabled; use isEnabled() for that. + * + * @param id operating mode unique ID + * @return True if that mode is the current mode + */ + public static boolean isOpMode(long id) { + return DriverStationBackend.isOpMode(id); + } + + /** + * Check to see if the selected operating mode is a particular value. Note this does not mean the + * robot is enabled; use isEnabled() for that. + * + * @param mode operating mode + * @return True if that mode is the current mode + */ + public static boolean isOpMode(String mode) { + return DriverStationBackend.isOpMode(mode); + } + + /** + * Gets a value indicating whether the Driver Station is attached. + * + * @return True if Driver Station is attached, false otherwise. + */ + public static boolean isDSAttached() { + return DriverStationBackend.isDSAttached(); + } + + /** + * Gets if the driver station attached to a Field Management System. + * + * @return true if the robot is competing on a field being controlled by a Field Management System + */ + public static boolean isFMSAttached() { + return DriverStationBackend.isFMSAttached(); + } +} diff --git a/wpilibj/src/main/java/org/wpilib/driverstation/TouchpadFinger.java b/wpilibj/src/main/java/org/wpilib/driverstation/TouchpadFinger.java new file mode 100644 index 0000000000..b4c7b1fbab --- /dev/null +++ b/wpilibj/src/main/java/org/wpilib/driverstation/TouchpadFinger.java @@ -0,0 +1,31 @@ +// 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.driverstation; + +/** Represents a finger on a touchpad. */ +@SuppressWarnings("MemberName") +public final class TouchpadFinger { + /** Whether the finger is touching the touchpad. */ + public final boolean down; + + /** The x position of the finger. 0 is at top left. */ + public final float x; + + /** The y position of the finger. 0 is at top left. */ + public final float y; + + /** + * Creates a TouchpadFinger object. + * + * @param down Whether the finger is touching the touchpad. + * @param x The x position of the finger. + * @param y The y position of the finger. + */ + public TouchpadFinger(boolean down, float x, float y) { + this.x = x; + this.y = y; + this.down = down; + } +} diff --git a/wpilibj/src/main/java/org/wpilib/driverstation/internal/DriverStationBackend.java b/wpilibj/src/main/java/org/wpilib/driverstation/internal/DriverStationBackend.java new file mode 100644 index 0000000000..ff4964dfc1 --- /dev/null +++ b/wpilibj/src/main/java/org/wpilib/driverstation/internal/DriverStationBackend.java @@ -0,0 +1,1863 @@ +// 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.driverstation.internal; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.OptionalDouble; +import java.util.OptionalInt; +import java.util.concurrent.locks.ReentrantLock; +import org.wpilib.datalog.BooleanArrayLogEntry; +import org.wpilib.datalog.DataLog; +import org.wpilib.datalog.FloatArrayLogEntry; +import org.wpilib.datalog.IntegerArrayLogEntry; +import org.wpilib.datalog.StringLogEntry; +import org.wpilib.datalog.StructLogEntry; +import org.wpilib.driverstation.Alliance; +import org.wpilib.driverstation.MatchType; +import org.wpilib.driverstation.POVDirection; +import org.wpilib.driverstation.TouchpadFinger; +import org.wpilib.framework.OpModeRobot; +import org.wpilib.framework.TimedRobot; +import org.wpilib.hardware.hal.AllianceStationID; +import org.wpilib.hardware.hal.ControlWord; +import org.wpilib.hardware.hal.DriverStationJNI; +import org.wpilib.hardware.hal.HAL; +import org.wpilib.hardware.hal.MatchInfoData; +import org.wpilib.hardware.hal.OpModeOption; +import org.wpilib.hardware.hal.RobotMode; +import org.wpilib.networktables.BooleanPublisher; +import org.wpilib.networktables.IntegerPublisher; +import org.wpilib.networktables.NetworkTableInstance; +import org.wpilib.networktables.StringPublisher; +import org.wpilib.networktables.StringTopic; +import org.wpilib.networktables.StructPublisher; +import org.wpilib.system.Timer; +import org.wpilib.util.Color; +import org.wpilib.util.WPIUtilJNI; +import org.wpilib.util.concurrent.EventVector; + +/** Provide access to the network communication data to / from the Driver Station. */ +public final class DriverStationBackend { + /** Number of Joystick ports. */ + public static final int JOYSTICK_PORTS = 6; + + private static final long[] m_metadataCache = new long[7]; + private static final float[] m_touchpadFingersCache = new float[8]; + + private static int availableToCount(long available) { + // Top bit has to be set + if (available < 0) { + return 64; + } + + int count = 0; + + // Top bit not set, we will eventually get a 0 bit + while ((available & 0x1) != 0) { + count++; + available >>= 1; + } + return count; + } + + private static final class HALJoystickTouchpadFinger { + public float m_x; + public float m_y; + public boolean m_down; + } + + private static class HALJoystickTouchpad { + public final HALJoystickTouchpadFinger[] m_fingers = + new HALJoystickTouchpadFinger[DriverStationJNI.MAX_JOYSTICK_TOUCHPAD_FINGERS]; + public int m_count; + + HALJoystickTouchpad() { + for (int i = 0; i < m_fingers.length; i++) { + m_fingers[i] = new HALJoystickTouchpadFinger(); + } + } + } + + private static class HALJoystickTouchpads { + public final HALJoystickTouchpad[] m_touchpads = + new HALJoystickTouchpad[DriverStationJNI.MAX_JOYSTICK_TOUCHPADS]; + public int m_count; + + HALJoystickTouchpads() { + for (int i = 0; i < m_touchpads.length; i++) { + m_touchpads[i] = new HALJoystickTouchpad(); + } + } + } + + private static final class HALJoystickButtons { + public long m_buttons; + public long m_available; + } + + private static class HALJoystickAxes { + public final float[] m_axes; + public int m_available; + + HALJoystickAxes(int count) { + m_axes = new float[count]; + } + } + + private static class HALJoystickAxesRaw { + public final short[] m_axes; + + @SuppressWarnings("unused") + public int m_available; + + HALJoystickAxesRaw(int count) { + m_axes = new short[count]; + } + } + + private static class HALJoystickPOVs { + public final byte[] m_povs; + public int m_available; + + HALJoystickPOVs(int count) { + m_povs = new byte[count]; + for (int i = 0; i < count; i++) { + m_povs[i] = 0; + } + } + } + + private static final double JOYSTICK_UNPLUGGED_MESSAGE_INTERVAL = 1.0; + private static double m_nextMessageTime; + + private static String opModeToString(long id) { + if (id == 0) { + return ""; + } + m_opModesMutex.lock(); + try { + OpModeOption option = m_opModes.get(id); + if (option != null) { + return option.name; + } + } finally { + m_opModesMutex.unlock(); + } + return "<" + id + ">"; + } + + @SuppressWarnings("MemberName") + private static class MatchDataSender { + private static final String kSmartDashboardType = "FMSInfo"; + + final StringPublisher gameData; + final StringPublisher eventName; + final IntegerPublisher matchNumber; + final IntegerPublisher replayNumber; + final IntegerPublisher matchType; + final BooleanPublisher alliance; + final IntegerPublisher station; + final StructPublisher controlWord; + final StringPublisher opMode; + boolean oldIsRedAlliance = true; + int oldStationNumber = 1; + String oldEventName = ""; + String oldGameData = ""; + int oldMatchNumber; + int oldReplayNumber; + int oldMatchType; + final ControlWord oldControlWord = new ControlWord(); + final ControlWord currentControlWord = new ControlWord(); + + MatchDataSender() { + var table = NetworkTableInstance.getDefault().getTable("FMSInfo"); + table + .getStringTopic(".type") + .publishEx( + StringTopic.TYPE_STRING, "{\"SmartDashboard\":\"" + kSmartDashboardType + "\"}") + .set(kSmartDashboardType); + gameData = table.getStringTopic("GameData").publish(); + gameData.set(""); + eventName = table.getStringTopic("EventName").publish(); + eventName.set(""); + matchNumber = table.getIntegerTopic("MatchNumber").publish(); + matchNumber.set(0); + replayNumber = table.getIntegerTopic("ReplayNumber").publish(); + replayNumber.set(0); + matchType = table.getIntegerTopic("MatchType").publish(); + matchType.set(0); + alliance = table.getBooleanTopic("IsRedAlliance").publish(); + alliance.set(true); + station = table.getIntegerTopic("StationNumber").publish(); + station.set(1); + controlWord = table.getStructTopic("ControlWord", ControlWord.struct).publish(); + controlWord.set(oldControlWord); + opMode = table.getStringTopic("OpMode").publish(); + opMode.set(""); + } + + @SuppressWarnings("VariableDeclarationUsageDistance") + private void sendMatchData() { + AllianceStationID allianceID = DriverStationJNI.getAllianceStation(); + final int stationNumber = + switch (allianceID) { + case BLUE_1, RED_1 -> 1; + case BLUE_2, RED_2 -> 2; + case BLUE_3, RED_3, UNKNOWN -> 3; + }; + final boolean isRedAlliance = + switch (allianceID) { + case BLUE_1, BLUE_2, BLUE_3 -> false; + case RED_1, RED_2, RED_3, UNKNOWN -> true; + }; + + String currentEventName; + String currentGameData; + int currentMatchNumber; + int currentReplayNumber; + int currentMatchType; + m_cacheDataMutex.lock(); + try { + currentEventName = DriverStationBackend.m_matchInfo.eventName; + currentGameData = DriverStationBackend.m_gameData; + currentMatchNumber = DriverStationBackend.m_matchInfo.matchNumber; + currentReplayNumber = DriverStationBackend.m_matchInfo.replayNumber; + currentMatchType = DriverStationBackend.m_matchInfo.matchType; + } finally { + m_cacheDataMutex.unlock(); + } + DriverStationJNI.getControlWord(currentControlWord); + + if (oldIsRedAlliance != isRedAlliance) { + alliance.set(isRedAlliance); + oldIsRedAlliance = isRedAlliance; + } + if (oldStationNumber != stationNumber) { + station.set(stationNumber); + oldStationNumber = stationNumber; + } + if (!oldEventName.equals(currentEventName)) { + eventName.set(currentEventName); + oldEventName = currentEventName; + } + if (!oldGameData.equals(currentGameData)) { + gameData.set(currentGameData); + oldGameData = currentGameData; + } + if (currentMatchNumber != oldMatchNumber) { + matchNumber.set(currentMatchNumber); + oldMatchNumber = currentMatchNumber; + } + if (currentReplayNumber != oldReplayNumber) { + replayNumber.set(currentReplayNumber); + oldReplayNumber = currentReplayNumber; + } + if (currentMatchType != oldMatchType) { + matchType.set(currentMatchType); + oldMatchType = currentMatchType; + } + if (!currentControlWord.equals(oldControlWord)) { + long currentOpModeId = currentControlWord.getOpModeId(); + if (currentOpModeId != oldControlWord.getOpModeId()) { + opMode.set(opModeToString(currentOpModeId)); + } + controlWord.set(currentControlWord); + oldControlWord.update(currentControlWord); + } + } + } + + private static class JoystickLogSender { + JoystickLogSender(DataLog log, int stick, long timestamp) { + m_stick = stick; + + m_logButtons = new BooleanArrayLogEntry(log, "DS:joystick" + stick + "/buttons", timestamp); + m_logAxes = new FloatArrayLogEntry(log, "DS:joystick" + stick + "/axes", timestamp); + m_logPOVs = new IntegerArrayLogEntry(log, "DS:joystick" + stick + "/povs", timestamp); + + appendButtons(m_joystickButtons[m_stick], timestamp); + appendAxes(m_joystickAxes[m_stick], timestamp); + appendPOVs(m_joystickPOVs[m_stick], timestamp); + } + + public void send(long timestamp) { + HALJoystickButtons buttons = m_joystickButtons[m_stick]; + if (buttons.m_available != m_prevButtons.m_available + || buttons.m_buttons != m_prevButtons.m_buttons) { + appendButtons(buttons, timestamp); + } + + HALJoystickAxes axes = m_joystickAxes[m_stick]; + int available = axes.m_available; + boolean needToLog = false; + if (available != m_prevAxes.m_available) { + needToLog = true; + } else { + for (int i = 0; i < m_prevAxes.m_axes.length; i++) { + if (axes.m_axes[i] != m_prevAxes.m_axes[i]) { + needToLog = true; + break; + } + } + } + if (needToLog) { + appendAxes(axes, timestamp); + } + + HALJoystickPOVs povs = m_joystickPOVs[m_stick]; + available = m_joystickPOVs[m_stick].m_available; + needToLog = false; + if (available != m_prevPOVs.m_available) { + needToLog = true; + } else { + for (int i = 0; i < m_prevPOVs.m_povs.length; i++) { + if (povs.m_povs[i] != m_prevPOVs.m_povs[i]) { + needToLog = true; + break; + } + } + } + if (needToLog) { + appendPOVs(povs, timestamp); + } + } + + void appendButtons(HALJoystickButtons buttons, long timestamp) { + int count = availableToCount(buttons.m_available); + if (m_sizedButtons == null || m_sizedButtons.length != count) { + m_sizedButtons = new boolean[count]; + } + long buttonsValue = buttons.m_buttons; + for (int i = 0; i < count; i++) { + m_sizedButtons[i] = (buttonsValue & (1L << i)) != 0; + } + m_logButtons.append(m_sizedButtons, timestamp); + m_prevButtons.m_available = buttons.m_available; + m_prevButtons.m_buttons = buttons.m_buttons; + } + + void appendAxes(HALJoystickAxes axes, long timestamp) { + int count = availableToCount(axes.m_available); + if (m_sizedAxes == null || m_sizedAxes.length != count) { + m_sizedAxes = new float[count]; + } + System.arraycopy(axes.m_axes, 0, m_sizedAxes, 0, count); + m_logAxes.append(m_sizedAxes, timestamp); + m_prevAxes.m_available = axes.m_available; + System.arraycopy(axes.m_axes, 0, m_prevAxes.m_axes, 0, count); + } + + void appendPOVs(HALJoystickPOVs povs, long timestamp) { + int count = availableToCount(povs.m_available); + if (m_sizedPOVs == null || m_sizedPOVs.length != count) { + m_sizedPOVs = new long[count]; + } + for (int i = 0; i < count; i++) { + m_sizedPOVs[i] = povs.m_povs[i]; + } + m_logPOVs.append(m_sizedPOVs, timestamp); + m_prevPOVs.m_available = povs.m_available; + System.arraycopy(povs.m_povs, 0, m_prevPOVs.m_povs, 0, count); + } + + final int m_stick; + boolean[] m_sizedButtons; + float[] m_sizedAxes; + long[] m_sizedPOVs; + final HALJoystickButtons m_prevButtons = new HALJoystickButtons(); + final HALJoystickAxes m_prevAxes = new HALJoystickAxes(DriverStationJNI.MAX_JOYSTICK_AXES); + final HALJoystickPOVs m_prevPOVs = new HALJoystickPOVs(DriverStationJNI.MAX_JOYSTICK_POVS); + final BooleanArrayLogEntry m_logButtons; + final FloatArrayLogEntry m_logAxes; + final IntegerArrayLogEntry m_logPOVs; + } + + private static class DataLogSender { + DataLogSender(DataLog log, boolean logJoysticks, long timestamp) { + m_logControlWord = + StructLogEntry.create(log, "DS:controlWord", ControlWord.struct, timestamp); + + // append initial control word value + m_logControlWord.append(m_controlWordCache, timestamp); + m_oldControlWord.update(m_controlWordCache); + + // append initial opmode value + m_logOpMode = new StringLogEntry(log, "DS:opMode", timestamp); + m_logOpMode.append(m_opModeCache, timestamp); + + if (logJoysticks) { + m_joysticks = new JoystickLogSender[JOYSTICK_PORTS]; + for (int i = 0; i < JOYSTICK_PORTS; i++) { + m_joysticks[i] = new JoystickLogSender(log, i, timestamp); + } + } else { + m_joysticks = new JoystickLogSender[0]; + } + } + + public void send(long timestamp) { + // append control word value changes + if (!m_controlWordCache.equals(m_oldControlWord)) { + // append opmode value changes + long opModeId = m_controlWordCache.getOpModeId(); + if (opModeId != m_oldControlWord.getOpModeId()) { + m_logOpMode.append(m_opModeCache, timestamp); + } + + m_logControlWord.append(m_controlWordCache, timestamp); + m_oldControlWord.update(m_controlWordCache); + } + + // append joystick value changes + for (JoystickLogSender joystick : m_joysticks) { + joystick.send(timestamp); + } + } + + final ControlWord m_oldControlWord = new ControlWord(); + final StructLogEntry m_logControlWord; + final StringLogEntry m_logOpMode; + + final JoystickLogSender[] m_joysticks; + } + + // Joystick User Data + private static HALJoystickAxes[] m_joystickAxes = new HALJoystickAxes[JOYSTICK_PORTS]; + private static HALJoystickAxesRaw[] m_joystickAxesRaw = new HALJoystickAxesRaw[JOYSTICK_PORTS]; + private static HALJoystickPOVs[] m_joystickPOVs = new HALJoystickPOVs[JOYSTICK_PORTS]; + private static HALJoystickButtons[] m_joystickButtons = new HALJoystickButtons[JOYSTICK_PORTS]; + private static HALJoystickTouchpads[] m_joystickTouchpads = + new HALJoystickTouchpads[JOYSTICK_PORTS]; + private static MatchInfoData m_matchInfo = new MatchInfoData(); + private static String m_gameData = ""; + private static ControlWord m_controlWord = new ControlWord(); + private static String m_opMode = ""; + private static EventVector m_refreshEvents = new EventVector(); + + // Joystick Cached Data + private static HALJoystickAxes[] m_joystickAxesCache = new HALJoystickAxes[JOYSTICK_PORTS]; + private static HALJoystickAxesRaw[] m_joystickAxesRawCache = + new HALJoystickAxesRaw[JOYSTICK_PORTS]; + private static HALJoystickPOVs[] m_joystickPOVsCache = new HALJoystickPOVs[JOYSTICK_PORTS]; + private static HALJoystickButtons[] m_joystickButtonsCache = + new HALJoystickButtons[JOYSTICK_PORTS]; + private static HALJoystickTouchpads[] m_joystickTouchpadsCache = + new HALJoystickTouchpads[JOYSTICK_PORTS]; + private static MatchInfoData m_matchInfoCache = new MatchInfoData(); + private static String m_gameDataCache = ""; + private static ControlWord m_controlWordCache = new ControlWord(); + + private static String m_opModeCache = ""; + + // Joystick button rising/falling edge flags + private static long[] m_joystickButtonsPressed = new long[JOYSTICK_PORTS]; + private static long[] m_joystickButtonsReleased = new long[JOYSTICK_PORTS]; + + private static final MatchDataSender m_matchDataSender; + private static DataLogSender m_dataLogSender; + + private static final ReentrantLock m_cacheDataMutex = new ReentrantLock(); + + private static boolean m_silenceJoystickWarning; + + private static boolean m_userProgramStarted = false; + private static final Map m_opModes = new HashMap<>(); + private static final ReentrantLock m_opModesMutex = new ReentrantLock(); + + /** + * DriverStation constructor. + * + *

The single DriverStation instance is created statically with the instance static member + * variable. + */ + private DriverStationBackend() {} + + static { + HAL.initialize(500, 0); + + for (int i = 0; i < JOYSTICK_PORTS; i++) { + m_joystickButtons[i] = new HALJoystickButtons(); + m_joystickAxes[i] = new HALJoystickAxes(DriverStationJNI.MAX_JOYSTICK_AXES); + m_joystickAxesRaw[i] = new HALJoystickAxesRaw(DriverStationJNI.MAX_JOYSTICK_AXES); + m_joystickPOVs[i] = new HALJoystickPOVs(DriverStationJNI.MAX_JOYSTICK_POVS); + m_joystickTouchpads[i] = new HALJoystickTouchpads(); + + m_joystickButtonsCache[i] = new HALJoystickButtons(); + m_joystickAxesCache[i] = new HALJoystickAxes(DriverStationJNI.MAX_JOYSTICK_AXES); + m_joystickAxesRawCache[i] = new HALJoystickAxesRaw(DriverStationJNI.MAX_JOYSTICK_AXES); + m_joystickPOVsCache[i] = new HALJoystickPOVs(DriverStationJNI.MAX_JOYSTICK_POVS); + m_joystickTouchpadsCache[i] = new HALJoystickTouchpads(); + } + + m_matchDataSender = new MatchDataSender(); + } + + /** + * Report error to Driver Station. Optionally appends Stack trace to error message. + * + * @param error The error to report. + * @param printTrace If true, append stack trace to error string + */ + public static void reportError(String error, boolean printTrace) { + reportErrorImpl(true, 1, error, printTrace); + } + + /** + * Report error to Driver Station. Appends provided stack trace to error message. + * + * @param error The error to report. + * @param stackTrace The stack trace to append + */ + public static void reportError(String error, StackTraceElement[] stackTrace) { + reportErrorImpl(true, 1, error, stackTrace); + } + + /** + * Report warning to Driver Station. Optionally appends Stack trace to warning message. + * + * @param warning The warning to report. + * @param printTrace If true, append stack trace to warning string + */ + public static void reportWarning(String warning, boolean printTrace) { + reportErrorImpl(false, 1, warning, printTrace); + } + + /** + * Report warning to Driver Station. Appends provided stack trace to warning message. + * + * @param warning The warning to report. + * @param stackTrace The stack trace to append + */ + public static void reportWarning(String warning, StackTraceElement[] stackTrace) { + reportErrorImpl(false, 1, warning, stackTrace); + } + + private static void reportErrorImpl(boolean isError, int code, String error, boolean printTrace) { + reportErrorImpl(isError, code, error, printTrace, Thread.currentThread().getStackTrace(), 3); + } + + private static void reportErrorImpl( + boolean isError, int code, String error, StackTraceElement[] stackTrace) { + reportErrorImpl(isError, code, error, true, stackTrace, 0); + } + + private static void reportErrorImpl( + boolean isError, + int code, + String error, + boolean printTrace, + StackTraceElement[] stackTrace, + int stackTraceFirst) { + String locString; + if (stackTrace.length >= stackTraceFirst + 1) { + locString = stackTrace[stackTraceFirst].toString(); + } else { + locString = ""; + } + StringBuilder traceString = new StringBuilder(); + if (printTrace) { + boolean haveLoc = false; + for (int i = stackTraceFirst; i < stackTrace.length; i++) { + String loc = stackTrace[i].toString(); + traceString.append("\tat ").append(loc).append('\n'); + // get first user function + if (!haveLoc && !loc.startsWith("org.wpilib")) { + locString = loc; + haveLoc = true; + } + } + } + DriverStationJNI.sendError( + isError, code, false, error, locString, traceString.toString(), true); + } + + /** + * The state of one joystick button. + * + * @param stick The joystick to read. + * @param button The button index. + * @return The state of the joystick button. + */ + public static boolean getStickButton(final int stick, final int button) { + if (stick < 0 || stick >= JOYSTICK_PORTS) { + throw new IllegalArgumentException("Joystick index is out of range, should be 0-5"); + } + if (button < 0 || button >= DriverStationJNI.MAX_JOYSTICK_BUTTONS) { + throw new IllegalArgumentException("Joystick Button is out of range"); + } + + long mask = 1L << button; + + m_cacheDataMutex.lock(); + try { + if ((m_joystickButtons[stick].m_available & mask) != 0) { + return (m_joystickButtons[stick].m_buttons & mask) != 0; + } + } finally { + m_cacheDataMutex.unlock(); + } + + reportJoystickWarning( + stick, "Joystick Button " + button + " on port " + stick + " not available"); + return false; + } + + /** + * The state of one joystick button if available. + * + * @param stick The joystick to read. + * @param button The button index. + * @return The state of the joystick button, or false if the button is not available. + */ + public static Optional getStickButtonIfAvailable(final int stick, final int button) { + if (stick < 0 || stick >= JOYSTICK_PORTS) { + throw new IllegalArgumentException("Joystick index is out of range, should be 0-5"); + } + if (button < 0 || button >= DriverStationJNI.MAX_JOYSTICK_BUTTONS) { + throw new IllegalArgumentException("Joystick Button is out of range"); + } + + long mask = 1L << button; + + m_cacheDataMutex.lock(); + try { + if ((m_joystickButtons[stick].m_available & mask) != 0) { + return Optional.of((m_joystickButtons[stick].m_buttons & mask) != 0); + } + } finally { + m_cacheDataMutex.unlock(); + } + return Optional.empty(); + } + + /** + * Whether one joystick button was pressed since the last check. + * + * @param stick The joystick to read. + * @param button The button index. + * @return Whether the joystick button was pressed since the last check. + */ + public static boolean getStickButtonPressed(final int stick, final int button) { + if (stick < 0 || stick >= JOYSTICK_PORTS) { + throw new IllegalArgumentException("Joystick index is out of range, should be 0-5"); + } + if (button < 0 || button >= DriverStationJNI.MAX_JOYSTICK_BUTTONS) { + throw new IllegalArgumentException("Joystick Button is out of range"); + } + + long mask = 1L << button; + + m_cacheDataMutex.lock(); + try { + if ((m_joystickButtons[stick].m_available & mask) != 0) { + // If button was pressed, clear flag and return true + if ((m_joystickButtonsPressed[stick] & mask) != 0) { + m_joystickButtonsPressed[stick] &= ~mask; + return true; + } else { + return false; + } + } + } finally { + m_cacheDataMutex.unlock(); + } + + reportJoystickWarning( + stick, "Joystick Button " + button + " on port " + stick + " not available"); + return false; + } + + /** + * Whether one joystick button was released since the last check. + * + * @param stick The joystick to read. + * @param button The button index, beginning at 0. + * @return Whether the joystick button was released since the last check. + */ + public static boolean getStickButtonReleased(final int stick, final int button) { + if (stick < 0 || stick >= JOYSTICK_PORTS) { + throw new IllegalArgumentException("Joystick index is out of range, should be 0-5"); + } + if (button < 0 || button >= DriverStationJNI.MAX_JOYSTICK_BUTTONS) { + throw new IllegalArgumentException("Joystick Button is out of range"); + } + + long mask = 1L << button; + + m_cacheDataMutex.lock(); + try { + if ((m_joystickButtons[stick].m_available & mask) != 0) { + // If button was released, clear flag and return true + if ((m_joystickButtonsReleased[stick] & mask) != 0) { + m_joystickButtonsReleased[stick] &= ~mask; + return true; + } else { + return false; + } + } + } finally { + m_cacheDataMutex.unlock(); + } + + reportJoystickWarning( + stick, "Joystick Button " + button + " on port " + stick + " not available"); + return false; + } + + /** + * Get the value of the axis on a joystick. This depends on the mapping of the joystick connected + * to the specified port. + * + * @param stick The joystick to read. + * @param axis The analog axis value to read from the joystick. + * @return The value of the axis on the joystick. + */ + public static double getStickAxis(int stick, int axis) { + if (stick < 0 || stick >= JOYSTICK_PORTS) { + throw new IllegalArgumentException("Joystick index is out of range, should be 0-5"); + } + if (axis < 0 || axis >= DriverStationJNI.MAX_JOYSTICK_AXES) { + throw new IllegalArgumentException("Joystick axis is out of range"); + } + + int mask = 1 << axis; + + m_cacheDataMutex.lock(); + try { + if ((m_joystickAxes[stick].m_available & mask) != 0) { + return m_joystickAxes[stick].m_axes[axis]; + } + } finally { + m_cacheDataMutex.unlock(); + } + + reportJoystickWarning(stick, "Joystick axis " + axis + " on port " + stick + " not available"); + return 0.0; + } + + /** + * Get the state of a touchpad finger on the joystick. + * + * @param stick The joystick to read. + * @param touchpad The touchpad to read. + * @param finger The finger to read. + * @return the state of the touchpad finger. + */ + public static TouchpadFinger getStickTouchpadFinger(int stick, int touchpad, int finger) { + if (stick < 0 || stick >= JOYSTICK_PORTS) { + throw new IllegalArgumentException("Joystick index is out of range, should be 0-5"); + } + if (touchpad < 0 || touchpad >= DriverStationJNI.MAX_JOYSTICK_TOUCHPADS) { + throw new IllegalArgumentException("Joystick touchpad is out of range"); + } + if (finger < 0 || finger >= DriverStationJNI.MAX_JOYSTICK_TOUCHPAD_FINGERS) { + throw new IllegalArgumentException("Joystick touchpad finger is out of range"); + } + + int touchpadCount; + m_cacheDataMutex.lock(); + try { + touchpadCount = m_joystickTouchpads[stick].m_count; + if (touchpad < touchpadCount) { + HALJoystickTouchpad tp = m_joystickTouchpads[stick].m_touchpads[touchpad]; + if (finger < tp.m_count) { + return new TouchpadFinger( + tp.m_fingers[finger].m_down, tp.m_fingers[finger].m_x, tp.m_fingers[finger].m_y); + } + } + } finally { + m_cacheDataMutex.unlock(); + } + + reportJoystickWarning( + stick, + "Joystick touchpad finger " + + finger + + " on touchpad " + + touchpad + + " on port " + + stick + + " not available"); + return new TouchpadFinger(false, 0.0f, 0.0f); + } + + /** + * Get whether a touchpad finger on the joystick is available. + * + * @param stick The joystick to read. + * @param touchpad The touchpad to read. + * @param finger The finger to read. + * @return whether the touchpad finger is available. + */ + public static boolean getStickTouchpadFingerAvailable(int stick, int touchpad, int finger) { + if (stick < 0 || stick >= JOYSTICK_PORTS) { + throw new IllegalArgumentException("Joystick index is out of range, should be 0-5"); + } + if (touchpad < 0 || touchpad >= DriverStationJNI.MAX_JOYSTICK_TOUCHPADS) { + throw new IllegalArgumentException("Joystick touchpad is out of range"); + } + if (finger < 0 || finger >= DriverStationJNI.MAX_JOYSTICK_TOUCHPAD_FINGERS) { + throw new IllegalArgumentException("Joystick touchpad finger is out of range"); + } + + int touchpadCount; + m_cacheDataMutex.lock(); + try { + touchpadCount = m_joystickTouchpads[stick].m_count; + if (touchpad < touchpadCount) { + HALJoystickTouchpad tp = m_joystickTouchpads[stick].m_touchpads[touchpad]; + if (finger < tp.m_count) { + return true; + } + } + } finally { + m_cacheDataMutex.unlock(); + } + + return false; + } + + /** + * Get the value of the axis on a joystick if available. This depends on the mapping of the + * joystick connected to the specified port. + * + * @param stick The joystick to read. + * @param axis The analog axis value to read from the joystick. + * @return The value of the axis on the joystick, or 0 if the axis is not available. + */ + public static OptionalDouble getStickAxisIfAvailable(int stick, int axis) { + if (stick < 0 || stick >= JOYSTICK_PORTS) { + throw new IllegalArgumentException("Joystick index is out of range, should be 0-5"); + } + if (axis < 0 || axis >= DriverStationJNI.MAX_JOYSTICK_AXES) { + throw new IllegalArgumentException("Joystick axis is out of range"); + } + + int mask = 1 << axis; + + m_cacheDataMutex.lock(); + try { + if ((m_joystickAxes[stick].m_available & mask) != 0) { + return OptionalDouble.of(m_joystickAxes[stick].m_axes[axis]); + } + } finally { + m_cacheDataMutex.unlock(); + } + + return OptionalDouble.empty(); + } + + /** + * Get the state of a POV on the joystick. + * + * @param stick The joystick to read. + * @param pov The POV to read. + * @return the angle of the POV. + */ + public static POVDirection getStickPOV(int stick, int pov) { + if (stick < 0 || stick >= JOYSTICK_PORTS) { + throw new IllegalArgumentException("Joystick index is out of range, should be 0-5"); + } + if (pov < 0 || pov >= DriverStationJNI.MAX_JOYSTICK_POVS) { + throw new IllegalArgumentException("Joystick POV is out of range"); + } + + int mask = 1 << pov; + + m_cacheDataMutex.lock(); + try { + if ((m_joystickPOVs[stick].m_available & mask) != 0) { + return POVDirection.of(m_joystickPOVs[stick].m_povs[pov]); + } + } finally { + m_cacheDataMutex.unlock(); + } + + reportJoystickWarning(stick, "Joystick POV " + pov + " on port " + stick + " not available"); + return POVDirection.CENTER; + } + + /** + * The state of the buttons on the joystick. + * + * @param stick The joystick to read. + * @return The state of the buttons on the joystick. + */ + public static long getStickButtons(final int stick) { + if (stick < 0 || stick >= JOYSTICK_PORTS) { + throw new IllegalArgumentException("Joystick index is out of range, should be 0-5"); + } + + m_cacheDataMutex.lock(); + try { + return m_joystickButtons[stick].m_buttons; + } finally { + m_cacheDataMutex.unlock(); + } + } + + /** + * Gets the maximum index of axes on a given joystick port. + * + * @param stick The joystick port number + * @return The maximum index of axes on the indicated joystick + */ + public static int getStickAxesMaximumIndex(int stick) { + return availableToCount(getStickAxesAvailable(stick)); + } + + /** + * Returns the available bitmask of axes on a given joystick port. + * + * @param stick The joystick port number + * @return The number of axes available on the indicated joystick + */ + public static int getStickAxesAvailable(int stick) { + if (stick < 0 || stick >= JOYSTICK_PORTS) { + throw new IllegalArgumentException("Joystick index is out of range, should be 0-5"); + } + + m_cacheDataMutex.lock(); + try { + return m_joystickAxes[stick].m_available; + } finally { + m_cacheDataMutex.unlock(); + } + } + + /** + * Gets the maximum index of povs on a given joystick port. + * + * @param stick The joystick port number + * @return The maximum index of povs on the indicated joystick + */ + public static int getStickPOVsMaximumIndex(int stick) { + return availableToCount(getStickPOVsAvailable(stick)); + } + + /** + * Returns the available bitmask of povs on a given joystick port. + * + * @param stick The joystick port number + * @return The number of povs available on the indicated joystick + */ + public static int getStickPOVsAvailable(int stick) { + if (stick < 0 || stick >= JOYSTICK_PORTS) { + throw new IllegalArgumentException("Joystick index is out of range, should be 0-5"); + } + + m_cacheDataMutex.lock(); + try { + return m_joystickPOVs[stick].m_available; + } finally { + m_cacheDataMutex.unlock(); + } + } + + /** + * Gets the maximum index of buttons on a given joystick port. + * + * @param stick The joystick port number + * @return The maximum index of buttons on the indicated joystick + */ + public static int getStickButtonsMaximumIndex(int stick) { + return availableToCount(getStickButtonsAvailable(stick)); + } + + /** + * Gets the bitmask of buttons available. + * + * @param stick The joystick port number + * @return The buttons available on the indicated joystick + */ + public static long getStickButtonsAvailable(int stick) { + if (stick < 0 || stick >= JOYSTICK_PORTS) { + throw new IllegalArgumentException("Joystick index is out of range, should be 0-5"); + } + + m_cacheDataMutex.lock(); + try { + return m_joystickButtons[stick].m_available; + } finally { + m_cacheDataMutex.unlock(); + } + } + + /** + * Gets the value of isGamepad on a joystick. + * + * @param stick The joystick port number + * @return A boolean that returns the value of isGamepad + */ + public static boolean getJoystickIsGamepad(int stick) { + if (stick < 0 || stick >= JOYSTICK_PORTS) { + throw new IllegalArgumentException("Joystick index is out of range, should be 0-5"); + } + + return DriverStationJNI.getJoystickIsGamepad((byte) stick) == 1; + } + + /** + * Gets the value of type on a gamepad. + * + * @param stick The joystick port number + * @return The value of type + */ + public static int getJoystickGamepadType(int stick) { + if (stick < 0 || stick >= JOYSTICK_PORTS) { + throw new IllegalArgumentException("Joystick index is out of range, should be 0-5"); + } + + return DriverStationJNI.getJoystickGamepadType((byte) stick); + } + + /** + * Gets the value of supported outputs on a joystick. + * + * @param stick The joystick port number + * @return The value of supported outputs + */ + public static int getJoystickSupportedOutputs(int stick) { + if (stick < 0 || stick >= JOYSTICK_PORTS) { + throw new IllegalArgumentException("Joystick index is out of range, should be 0-5"); + } + + return DriverStationJNI.getJoystickSupportedOutputs((byte) stick); + } + + /** + * Gets the name of the joystick at a port. + * + * @param stick The joystick port number + * @return The value of name + */ + public static String getJoystickName(int stick) { + if (stick < 0 || stick >= JOYSTICK_PORTS) { + throw new IllegalArgumentException("Joystick index is out of range, should be 0-5"); + } + + return DriverStationJNI.getJoystickName((byte) stick); + } + + /** + * Returns if a joystick is connected to the Driver Station. + * + *

This makes a best effort guess by looking at the reported number of axis, buttons, and POVs + * attached. + * + * @param stick The joystick port number + * @return true if a joystick is connected + */ + public static boolean isJoystickConnected(int stick) { + return getStickAxesAvailable(stick) != 0 + || getStickButtonsAvailable(stick) != 0 + || getStickPOVsAvailable(stick) != 0; + } + + /** + * Gets a value indicating whether the Driver Station requires the robot to be enabled. + * + * @return True if the robot is enabled, false otherwise. + */ + public static boolean isEnabled() { + m_cacheDataMutex.lock(); + try { + return m_controlWord.isEnabled() && m_controlWord.isDSAttached(); + } finally { + m_cacheDataMutex.unlock(); + } + } + + /** + * Gets a value indicating whether the Driver Station requires the robot to be disabled. + * + * @return True if the robot should be disabled, false otherwise. + */ + public static boolean isDisabled() { + return !isEnabled(); + } + + /** + * Gets a value indicating whether the Robot is e-stopped. + * + * @return True if the robot is e-stopped, false otherwise. + */ + public static boolean isEStopped() { + m_cacheDataMutex.lock(); + try { + return m_controlWord.isEStopped(); + } finally { + m_cacheDataMutex.unlock(); + } + } + + /** + * Gets the current robot mode. + * + *

Note that this does not indicate whether the robot is enabled or disabled. + * + * @return robot mode + */ + public static RobotMode getRobotMode() { + m_cacheDataMutex.lock(); + try { + return m_controlWord.getRobotMode(); + } finally { + m_cacheDataMutex.unlock(); + } + } + + /** + * Gets a value indicating whether the Driver Station requires the robot to be running in + * autonomous mode. + * + * @return True if autonomous mode should be enabled, false otherwise. + */ + public static boolean isAutonomous() { + m_cacheDataMutex.lock(); + try { + return m_controlWord.isAutonomous(); + } finally { + m_cacheDataMutex.unlock(); + } + } + + /** + * Gets a value indicating whether the Driver Station requires the robot to be running in + * autonomous mode and enabled. + * + * @return True if autonomous should be set and the robot should be enabled. + */ + public static boolean isAutonomousEnabled() { + m_cacheDataMutex.lock(); + try { + return m_controlWord.isAutonomousEnabled(); + } finally { + m_cacheDataMutex.unlock(); + } + } + + /** + * Gets a value indicating whether the Driver Station requires the robot to be running in + * operator-controlled mode. + * + * @return True if operator-controlled mode should be enabled, false otherwise. + */ + public static boolean isTeleop() { + return m_controlWord.isTeleop(); + } + + /** + * Gets a value indicating whether the Driver Station requires the robot to be running in + * operator-controller mode and enabled. + * + * @return True if operator-controlled mode should be set and the robot should be enabled. + */ + public static boolean isTeleopEnabled() { + m_cacheDataMutex.lock(); + try { + return m_controlWord.isTeleopEnabled(); + } finally { + m_cacheDataMutex.unlock(); + } + } + + /** + * Gets a value indicating whether the Driver Station requires the robot to be running in Test + * mode. + * + * @return True if test mode should be enabled, false otherwise. + */ + public static boolean isTest() { + m_cacheDataMutex.lock(); + try { + return m_controlWord.isTest(); + } finally { + m_cacheDataMutex.unlock(); + } + } + + /** + * Gets a value indicating whether the Driver Station requires the robot to be running in Test + * mode and enabled. + * + * @return True if test mode should be set and the robot should be enabled. + */ + public static boolean isTestEnabled() { + m_cacheDataMutex.lock(); + try { + return m_controlWord.isTestEnabled(); + } finally { + m_cacheDataMutex.unlock(); + } + } + + private static int convertColorToInt(Color color) { + if (color == null) { + return -1; + } + return (((int) (color.red * 255) & 0xff) << 16) + | (((int) (color.green * 255) & 0xff) << 8) + | ((int) (color.blue * 255) & 0xff); + } + + /** + * Adds an operating mode option. It's necessary to call publishOpModes() to make the added modes + * visible to the driver station. + * + * @param mode robot mode + * @param name name of the operating mode + * @param group group of the operating mode + * @param description description of the operating mode + * @param textColor text color, or null for default + * @param backgroundColor background color, or null for default + * @return unique ID used to later identify the operating mode + * @throws IllegalArgumentException if name is empty or an operating mode with the same robot mode + * and name already exists + */ + @SuppressWarnings("PMD.UseStringBufferForStringAppends") + public static long addOpMode( + RobotMode mode, + String name, + String group, + String description, + Color textColor, + Color backgroundColor) { + if (name.isBlank()) { + throw new IllegalArgumentException("OpMode name must be non-blank"); + } + // find unique ID + m_opModesMutex.lock(); + try { + String nameCopy = name; + for (; ; ) { + long id = OpModeOption.makeId(mode, nameCopy.hashCode()); + OpModeOption existing = m_opModes.get(id); + if (existing == null) { + m_opModes.put( + id, + new OpModeOption( + id, + name, + group, + description, + convertColorToInt(textColor), + convertColorToInt(backgroundColor))); + return id; + } + if (existing.getMode() == mode && existing.name.equals(name)) { + // already exists + throw new IllegalArgumentException("OpMode " + name + " already exists for mode " + mode); + } + // collision, try again with space appended + nameCopy += ' '; + } + } finally { + m_opModesMutex.unlock(); + } + } + + /** + * Adds an operating mode option. It's necessary to call publishOpModes() to make the added modes + * visible to the driver station. + * + * @param mode robot mode + * @param name name of the operating mode + * @param group group of the operating mode + * @param description description of the operating mode + * @return unique ID used to later identify the operating mode + * @throws IllegalArgumentException if name is empty or an operating mode with the same name + * already exists + */ + public static long addOpMode(RobotMode mode, String name, String group, String description) { + return addOpMode(mode, name, group, description, null, null); + } + + /** + * Adds an operating mode option. It's necessary to call publishOpModes() to make the added modes + * visible to the driver station. + * + * @param mode robot mode + * @param name name of the operating mode + * @param group group of the operating mode + * @return unique ID used to later identify the operating mode + * @throws IllegalArgumentException if name is empty or an operating mode with the same name + * already exists + */ + public static long addOpMode(RobotMode mode, String name, String group) { + return addOpMode(mode, name, group, ""); + } + + /** + * Adds an operating mode option. It's necessary to call publishOpModes() to make the added modes + * visible to the driver station. + * + * @param mode robot mode + * @param name name of the operating mode + * @return unique ID used to later identify the operating mode + * @throws IllegalArgumentException if name is empty or an operating mode with the same name + * already exists + */ + public static long addOpMode(RobotMode mode, String name) { + return addOpMode(mode, name, ""); + } + + /** + * Removes an operating mode option. It's necessary to call publishOpModes() to make the removed + * mode no longer visible to the driver station. + * + * @param mode robot mode + * @param name name of the operating mode + * @return unique ID for the opmode, or 0 if not found + */ + public static long removeOpMode(RobotMode mode, String name) { + if (name.isBlank()) { + return 0; + } + m_opModesMutex.lock(); + try { + // we have to loop over all entries to find the one with the correct name + // because the of the unique ID generation scheme + for (OpModeOption opMode : m_opModes.values()) { + if (opMode.getMode() == mode && opMode.name.equals(name)) { + m_opModes.remove(opMode.id); + return opMode.id; + } + } + } finally { + m_opModesMutex.unlock(); + } + return 0; + } + + /** Publishes the operating mode options to the driver station. */ + public static void publishOpModes() { + m_opModesMutex.lock(); + try { + OpModeOption[] options = new OpModeOption[m_opModes.size()]; + DriverStationJNI.setOpModeOptions(m_opModes.values().toArray(options)); + } finally { + m_opModesMutex.unlock(); + } + } + + /** Clears all operating mode options and publishes an empty list to the driver station. */ + public static void clearOpModes() { + m_opModesMutex.lock(); + try { + m_opModes.clear(); + DriverStationJNI.setOpModeOptions(new OpModeOption[0]); + } finally { + m_opModesMutex.unlock(); + } + } + + /** + * Sets the program starting flag in the DS. This will also allow {@link #getOpModeId()} and + * {@link #getOpMode()} to return values for the selected OpMode in the DS application, if the DS + * is connected by the time this method is called. + * + *

Most users will not need to use this method; the {@link TimedRobot} and {@link OpModeRobot} + * robot framework classes will call it automatically after the main robot class is instantiated. + * However, teams using the commandsv3 library and a custom main robot class need to be careful to + * only call this method after all mechanisms and global trigger bindings are set up. If not, any + * setup performed in the main robot class may be incorrectly bound to the opmode selected in the + * DS if it's connected by the time the robot program boots up. + * + *

This is what changes the DS to showing robot code ready. + * + * @see #getOpMode() + * @see #getOpModeId() + */ + public static void observeUserProgramStarting() { + m_userProgramStarted = true; + DriverStationJNI.observeUserProgramStarting(); + } + + /** + * Gets the operating mode selected on the driver station. Note this does not mean the robot is + * enabled; use isEnabled() for that. In a match, this will indicate the operating mode selected + * for auto before the match starts (i.e., while the robot is disabled in auto mode); after the + * auto period ends, this will change to reflect the operating mode selected for teleop. + * + *

This method always returns {@code 0} while the main robot class is being constructed and + * initialized (more specifically, it returns {@code 0} until {@link + * #observeUserProgramStarting()} is called, which the WPILib framework will automatically call + * during {@link TimedRobot#startCompetition()} and {@link OpModeRobot#startCompetition()}). + * + * @return the unique ID provided by the addOpMode() function; may return 0 or a unique ID not + * added, so callers should be prepared to handle that case + */ + public static long getOpModeId() { + if (!m_userProgramStarted) { + return 0; + } + + m_cacheDataMutex.lock(); + try { + return m_controlWord.getOpModeId(); + } finally { + m_cacheDataMutex.unlock(); + } + } + + /** + * Gets the operating mode selected on the driver station. Note this does not mean the robot is + * enabled; use isEnabled() for that. In a match, this will indicate the operating mode selected + * for auto before the match starts (i.e., while the robot is disabled in auto mode); after the + * auto period ends, this will change to reflect the operating mode selected for teleop. + * + *

This method always returns an empty string {@code ""} while the main robot class is being + * constructed and initialized (more specifically, it returns {@code ""} until {@link + * #observeUserProgramStarting()} is called, which the WPILib framework will automatically call + * during {@link TimedRobot#startCompetition()} and {@link OpModeRobot#startCompetition()}). + * + * @return Operating mode string; may return a string not in the list of options, so callers + * should be prepared to handle that case + */ + public static String getOpMode() { + if (!m_userProgramStarted) { + return ""; + } + + m_cacheDataMutex.lock(); + try { + return m_opMode; + } finally { + m_cacheDataMutex.unlock(); + } + } + + /** + * Check to see if the selected operating mode is a particular value. Note this does not mean the + * robot is enabled; use isEnabled() for that. + * + * @param id operating mode unique ID + * @return True if that mode is the current mode + */ + public static boolean isOpMode(long id) { + return getOpModeId() == id; + } + + /** + * Check to see if the selected operating mode is a particular value. Note this does not mean the + * robot is enabled; use isEnabled() for that. + * + * @param mode operating mode + * @return True if that mode is the current mode + */ + public static boolean isOpMode(String mode) { + return getOpMode().equals(mode); + } + + /** + * Gets a value indicating whether the Driver Station is attached. + * + * @return True if Driver Station is attached, false otherwise. + */ + public static boolean isDSAttached() { + m_cacheDataMutex.lock(); + try { + return m_controlWord.isDSAttached(); + } finally { + m_cacheDataMutex.unlock(); + } + } + + /** + * Gets if the driver station attached to a Field Management System. + * + * @return true if the robot is competing on a field being controlled by a Field Management System + */ + public static boolean isFMSAttached() { + m_cacheDataMutex.lock(); + try { + return m_controlWord.isFMSAttached(); + } finally { + m_cacheDataMutex.unlock(); + } + } + + /** + * Get the game specific message from the FMS. + * + *

If the FMS is not connected, it is set from the game data setting on the driver station. + * + * @return the game specific message + */ + public static Optional getGameData() { + m_cacheDataMutex.lock(); + try { + if (m_gameData == null || m_gameData.isEmpty()) { + return Optional.empty(); + } + return Optional.of(m_gameData); + } finally { + m_cacheDataMutex.unlock(); + } + } + + /** + * Get the event name from the FMS. + * + * @return the event name + */ + public static String getEventName() { + m_cacheDataMutex.lock(); + try { + return m_matchInfo.eventName; + } finally { + m_cacheDataMutex.unlock(); + } + } + + /** + * Get the match type from the FMS. + * + * @return the match type + */ + public static MatchType getMatchType() { + int matchType; + m_cacheDataMutex.lock(); + try { + matchType = m_matchInfo.matchType; + } finally { + m_cacheDataMutex.unlock(); + } + return switch (matchType) { + case 1 -> MatchType.PRACTICE; + case 2 -> MatchType.QUALIFICATION; + case 3 -> MatchType.ELIMINATION; + default -> MatchType.NONE; + }; + } + + /** + * Get the match number from the FMS. + * + * @return the match number + */ + public static int getMatchNumber() { + m_cacheDataMutex.lock(); + try { + return m_matchInfo.matchNumber; + } finally { + m_cacheDataMutex.unlock(); + } + } + + /** + * Get the replay number from the FMS. + * + * @return the replay number + */ + public static int getReplayNumber() { + m_cacheDataMutex.lock(); + try { + return m_matchInfo.replayNumber; + } finally { + m_cacheDataMutex.unlock(); + } + } + + private static Map> m_allianceMap = + Map.of( + AllianceStationID.UNKNOWN, Optional.empty(), + AllianceStationID.RED_1, Optional.of(Alliance.RED), + AllianceStationID.RED_2, Optional.of(Alliance.RED), + AllianceStationID.RED_3, Optional.of(Alliance.RED), + AllianceStationID.BLUE_1, Optional.of(Alliance.BLUE), + AllianceStationID.BLUE_2, Optional.of(Alliance.BLUE), + AllianceStationID.BLUE_3, Optional.of(Alliance.BLUE)); + + private static Map m_stationMap = + Map.of( + AllianceStationID.UNKNOWN, OptionalInt.empty(), + AllianceStationID.RED_1, OptionalInt.of(1), + AllianceStationID.RED_2, OptionalInt.of(2), + AllianceStationID.RED_3, OptionalInt.of(3), + AllianceStationID.BLUE_1, OptionalInt.of(1), + AllianceStationID.BLUE_2, OptionalInt.of(2), + AllianceStationID.BLUE_3, OptionalInt.of(3)); + + /** + * Get the current alliance from the FMS. + * + *

If the FMS is not connected, it is set from the team alliance setting on the driver station. + * + * @return The alliance (red or blue) or an empty optional if the alliance is invalid + */ + public static Optional getAlliance() { + AllianceStationID allianceStationID = DriverStationJNI.getAllianceStation(); + if (allianceStationID == null) { + allianceStationID = AllianceStationID.UNKNOWN; + } + + return m_allianceMap.get(allianceStationID); + } + + /** + * Gets the location of the team's driver station controls from the FMS. + * + *

If the FMS is not connected, it is set from the team alliance setting on the driver station. + * + * @return the location of the team's driver station controls: 1, 2, or 3 + */ + public static OptionalInt getLocation() { + AllianceStationID allianceStationID = DriverStationJNI.getAllianceStation(); + if (allianceStationID == null) { + allianceStationID = AllianceStationID.UNKNOWN; + } + + return m_stationMap.get(allianceStationID); + } + + /** + * Gets the raw alliance station of the teams driver station. + * + *

This returns the raw low level value. Prefer getLocation or getAlliance unless necessary for + * performance. + * + * @return The raw alliance station id. + */ + public static AllianceStationID getRawAllianceStation() { + return DriverStationJNI.getAllianceStation(); + } + + /** + * Return the approximate match time. The FMS does not send an official match time to the robots, + * but does send an approximate match time. The value will count down the time remaining in the + * current period (auto or teleop). Warning: This is not an official time (so it cannot be used to + * dispute ref calls or guarantee that a function will trigger before the match ends). + * + *

When connected to the real field, this number only changes in full integer increments, and + * always counts down. + * + *

When the DS is in practice mode, this number is a floating point number, and counts down. + * + *

When the DS is in teleop or autonomous mode, this number returns -1.0. + * + *

Simulation matches DS behavior without an FMS connected. + * + * @return Time remaining in current match period (auto or teleop) in seconds + */ + public static double getMatchTime() { + return DriverStationJNI.getMatchTime(); + } + + /** + * Allows the user to specify whether they want joystick connection warnings to be printed to the + * console. This setting is ignored when the FMS is connected -- warnings will always be on in + * that scenario. + * + * @param silence Whether warning messages should be silenced. + */ + public static void silenceJoystickConnectionWarning(boolean silence) { + m_silenceJoystickWarning = silence; + } + + /** + * Returns whether joystick connection warnings are silenced. This will always return false when + * connected to the FMS. + * + * @return Whether joystick connection warnings are silenced. + */ + public static boolean isJoystickConnectionWarningSilenced() { + return !isFMSAttached() && m_silenceJoystickWarning; + } + + /** + * Refresh the passed in control word to contain the current control word cache. + * + * @param word Word to refresh. + */ + public static void refreshControlWordFromCache(ControlWord word) { + m_cacheDataMutex.lock(); + try { + word.update(m_controlWord); + } finally { + m_cacheDataMutex.unlock(); + } + } + + /** + * Copy data from the DS task for the user. If no new data exists, it will just be returned, + * otherwise the data will be copied from the DS polling loop. + */ + public static void refreshData() { + DriverStationJNI.refreshDSData(); + + // Get the status of all the joysticks + for (byte stick = 0; stick < JOYSTICK_PORTS; stick++) { + DriverStationJNI.getAllJoystickData( + stick, + m_joystickAxesCache[stick].m_axes, + m_joystickAxesRawCache[stick].m_axes, + m_joystickPOVsCache[stick].m_povs, + m_touchpadFingersCache, + m_metadataCache); + m_joystickAxesCache[stick].m_available = (int) m_metadataCache[0]; + m_joystickAxesRawCache[stick].m_available = (int) m_metadataCache[0]; + m_joystickPOVsCache[stick].m_available = (int) m_metadataCache[1]; + m_joystickButtonsCache[stick].m_available = m_metadataCache[2]; + m_joystickButtonsCache[stick].m_buttons = m_metadataCache[3]; + m_joystickTouchpadsCache[stick].m_count = (int) m_metadataCache[4]; + for (int i = 0; i < m_joystickTouchpadsCache[stick].m_count; i++) { + long metadata = m_metadataCache[5 + i]; + m_joystickTouchpadsCache[stick].m_touchpads[i].m_fingers[0].m_down = (metadata & 0x1) != 0; + m_joystickTouchpadsCache[stick].m_touchpads[i].m_fingers[1].m_down = (metadata & 0x2) != 0; + m_joystickTouchpadsCache[stick].m_touchpads[i].m_count = (int) (metadata >> 2 & 0x3); + for (int j = 0; j < m_joystickTouchpadsCache[stick].m_touchpads[i].m_count; j++) { + m_joystickTouchpadsCache[stick].m_touchpads[i].m_fingers[j].m_x = + m_touchpadFingersCache[i * 4 + j * 2 + 0]; + m_joystickTouchpadsCache[stick].m_touchpads[i].m_fingers[j].m_y = + m_touchpadFingersCache[i * 4 + j * 2 + 1]; + } + } + } + + DriverStationJNI.getMatchInfo(m_matchInfoCache); + + // This is a pass through, so if it hasn't changed, it doesn't + // reallocate + m_gameDataCache = DriverStationJNI.getGameData(m_gameDataCache); + + DriverStationJNI.getControlWord(m_controlWordCache); + + m_opModeCache = opModeToString(m_controlWordCache.getOpModeId()); + + DataLogSender dataLogSender; + // lock joystick mutex to swap cache data + m_cacheDataMutex.lock(); + try { + for (int i = 0; i < JOYSTICK_PORTS; i++) { + // If buttons weren't pressed and are now, set flags in m_buttonsPressed + m_joystickButtonsPressed[i] |= + ~m_joystickButtons[i].m_buttons & m_joystickButtonsCache[i].m_buttons; + + // If buttons were pressed and aren't now, set flags in m_buttonsReleased + m_joystickButtonsReleased[i] |= + m_joystickButtons[i].m_buttons & ~m_joystickButtonsCache[i].m_buttons; + } + + // move cache to actual data + HALJoystickAxes[] currentAxes = m_joystickAxes; + m_joystickAxes = m_joystickAxesCache; + m_joystickAxesCache = currentAxes; + + HALJoystickAxesRaw[] currentAxesRaw = m_joystickAxesRaw; + m_joystickAxesRaw = m_joystickAxesRawCache; + m_joystickAxesRawCache = currentAxesRaw; + + HALJoystickButtons[] currentButtons = m_joystickButtons; + m_joystickButtons = m_joystickButtonsCache; + m_joystickButtonsCache = currentButtons; + + HALJoystickPOVs[] currentPOVs = m_joystickPOVs; + m_joystickPOVs = m_joystickPOVsCache; + m_joystickPOVsCache = currentPOVs; + + HALJoystickTouchpads[] currentTouchpads = m_joystickTouchpads; + m_joystickTouchpads = m_joystickTouchpadsCache; + m_joystickTouchpadsCache = currentTouchpads; + + MatchInfoData currentInfo = m_matchInfo; + m_matchInfo = m_matchInfoCache; + m_matchInfoCache = currentInfo; + + m_gameData = m_gameDataCache; + + ControlWord currentWord = m_controlWord; + m_controlWord = m_controlWordCache; + m_controlWordCache = currentWord; + + String currentOpMode = m_opMode; + m_opMode = m_opModeCache; + m_opModeCache = currentOpMode; + + dataLogSender = m_dataLogSender; + } finally { + m_cacheDataMutex.unlock(); + } + + m_refreshEvents.wakeup(); + + m_matchDataSender.sendMatchData(); + if (dataLogSender != null) { + dataLogSender.send(WPIUtilJNI.now()); + } + } + + /** + * Registers the given handle for DS data refresh notifications. + * + * @param handle The event handle. + */ + public static void provideRefreshedDataEventHandle(int handle) { + m_refreshEvents.add(handle); + } + + /** + * Unregisters the given handle from DS data refresh notifications. + * + * @param handle The event handle. + */ + public static void removeRefreshedDataEventHandle(int handle) { + m_refreshEvents.remove(handle); + } + + /** + * Reports errors related to joystick availability. Throttles the errors so that they don't + * overwhelm the DS. + * + * @param stick The joystick port. + * @param message The message to report if the joystick is connected. + */ + private static void reportJoystickWarning(int stick, String message) { + if (isFMSAttached() || !m_silenceJoystickWarning) { + double currentTime = Timer.getTimestamp(); + if (currentTime > m_nextMessageTime) { + if (isJoystickConnected(stick)) { + reportWarning(message, false); + } else { + reportWarning( + "Joystick on port " + stick + " not available, check if controller is plugged in", + false); + } + m_nextMessageTime = currentTime + JOYSTICK_UNPLUGGED_MESSAGE_INTERVAL; + } + } + } + + /** + * Starts logging DriverStation data to data log. Repeated calls are ignored. + * + * @param log data log + * @param logJoysticks if true, log joystick data + */ + @SuppressWarnings("PMD.NonThreadSafeSingleton") + public static void startDataLog(DataLog log, boolean logJoysticks) { + m_cacheDataMutex.lock(); + try { + if (m_dataLogSender == null) { + m_dataLogSender = new DataLogSender(log, logJoysticks, WPIUtilJNI.now()); + } + } finally { + m_cacheDataMutex.unlock(); + } + } + + /** + * Starts logging DriverStation data to data log, including joystick data. Repeated calls are + * ignored. + * + * @param log data log + */ + public static void startDataLog(DataLog log) { + startDataLog(log, true); + } +} diff --git a/wpilibj/src/main/java/org/wpilib/framework/IterativeRobotBase.java b/wpilibj/src/main/java/org/wpilib/framework/IterativeRobotBase.java index baa63126c6..b8a2a42e89 100644 --- a/wpilibj/src/main/java/org/wpilib/framework/IterativeRobotBase.java +++ b/wpilibj/src/main/java/org/wpilib/framework/IterativeRobotBase.java @@ -4,7 +4,8 @@ package org.wpilib.framework; -import org.wpilib.driverstation.DriverStation; +import org.wpilib.driverstation.DriverStationErrors; +import org.wpilib.driverstation.internal.DriverStationBackend; import org.wpilib.hardware.hal.ControlWord; import org.wpilib.hardware.hal.DriverStationJNI; import org.wpilib.hardware.hal.HAL; @@ -236,8 +237,8 @@ public abstract class IterativeRobotBase extends RobotBase { /** Loop function. */ protected final void loopFunc() { - DriverStation.refreshData(); - DriverStation.refreshControlWordFromCache(m_word); + DriverStationBackend.refreshData(); + DriverStationBackend.refreshControlWordFromCache(m_word); m_watchdog.reset(); // Get current mode; treat disabled as unknown @@ -344,6 +345,6 @@ public abstract class IterativeRobotBase extends RobotBase { } private void printLoopOverrunMessage() { - DriverStation.reportWarning("Loop time of " + m_period + "s overrun\n", false); + DriverStationErrors.reportWarning("Loop time of " + m_period + "s overrun\n", false); } } diff --git a/wpilibj/src/main/java/org/wpilib/framework/OpModeRobot.java b/wpilibj/src/main/java/org/wpilib/framework/OpModeRobot.java index 7869f66079..f652d391e2 100644 --- a/wpilibj/src/main/java/org/wpilib/framework/OpModeRobot.java +++ b/wpilibj/src/main/java/org/wpilib/framework/OpModeRobot.java @@ -20,9 +20,11 @@ import java.util.function.Supplier; import java.util.jar.JarEntry; import java.util.jar.JarFile; import org.wpilib.driverstation.Alert; -import org.wpilib.driverstation.DriverStation; +import org.wpilib.driverstation.DriverStationErrors; +import org.wpilib.driverstation.RobotState; import org.wpilib.driverstation.UserControls; import org.wpilib.driverstation.UserControlsInstance; +import org.wpilib.driverstation.internal.DriverStationBackend; import org.wpilib.hardware.hal.ControlWord; import org.wpilib.hardware.hal.DriverStationJNI; import org.wpilib.hardware.hal.HAL; @@ -82,7 +84,8 @@ public abstract class OpModeRobot extends RobotBase { private final Alert m_loopOverrunAlert; private static void reportAddOpModeError(Class cls, String message) { - DriverStation.reportError("Error adding OpMode " + cls.getSimpleName() + ": " + message, false); + DriverStationErrors.reportError( + "Error adding OpMode " + cls.getSimpleName() + ": " + message, false); } private final Optional> m_userControlsBaseClass; @@ -142,7 +145,7 @@ public abstract class OpModeRobot extends RobotBase { private T constructOpModeClass(Class cls) { Optional> constructor = findOpModeConstructor(cls); if (constructor.isEmpty()) { - DriverStation.reportError( + DriverStationErrors.reportError( "No suitable constructor to instantiate OpMode " + cls.getSimpleName(), true); return null; } @@ -153,7 +156,7 @@ public abstract class OpModeRobot extends RobotBase { return constructor.get().newInstance(this); } } catch (ReflectiveOperationException e) { - DriverStation.reportError( + DriverStationErrors.reportError( "Could not instantiate OpMode " + cls.getSimpleName(), e.getStackTrace()); return null; } @@ -207,7 +210,7 @@ public abstract class OpModeRobot extends RobotBase { String description, Color textColor, Color backgroundColor) { - long id = DriverStation.addOpMode(mode, name, group, description, textColor, backgroundColor); + long id = RobotState.addOpMode(mode, name, group, description, textColor, backgroundColor); m_opModes.put(id, new OpModeFactory(name, factory)); } @@ -355,7 +358,7 @@ public abstract class OpModeRobot extends RobotBase { } Color tColor = textColor.isBlank() ? null : Color.fromString(textColor); Color bColor = backgroundColor.isBlank() ? null : Color.fromString(backgroundColor); - long id = DriverStation.addOpMode(mode, name, group, description, tColor, bColor); + long id = RobotState.addOpMode(mode, name, group, description, tColor, bColor); m_opModes.put(id, new OpModeFactory(name, () -> constructOpModeClass(cls))); } @@ -504,7 +507,7 @@ public abstract class OpModeRobot extends RobotBase { * @param name name of the operating mode */ public void removeOpMode(RobotMode mode, String name) { - long id = DriverStation.removeOpMode(mode, name); + long id = RobotState.removeOpMode(mode, name); if (id != 0) { m_opModes.remove(id); } @@ -512,12 +515,12 @@ public abstract class OpModeRobot extends RobotBase { /** Publishes the operating mode options to the driver station. */ public void publishOpModes() { - DriverStation.publishOpModes(); + RobotState.publishOpModes(); } /** Clears all operating mode options and publishes an empty list to the driver station. */ public void clearOpModes() { - DriverStation.clearOpModes(); + RobotState.clearOpModes(); m_opModes.clear(); } @@ -562,7 +565,7 @@ public abstract class OpModeRobot extends RobotBase { } // Scan for annotated opmode classes within the derived class's package and subpackages addAnnotatedOpModeClasses(getClass().getPackage()); - DriverStation.publishOpModes(); + RobotState.publishOpModes(); HAL.reportUsage("Framework", "OpModeRobot"); } @@ -631,10 +634,10 @@ public abstract class OpModeRobot extends RobotBase { /** Main robot loop function. Handles disabled state logic and opmode management. */ private void loopFunc() { - DriverStation.refreshData(); + DriverStationBackend.refreshData(); // Get current enabled state and opmode - DriverStation.refreshControlWordFromCache(m_word); + DriverStationBackend.refreshControlWordFromCache(m_word); m_watchdog.reset(); boolean enabled = m_word.isEnabled(); long modeId = m_word.isDSAttached() ? m_word.getOpModeId() : 0; @@ -676,7 +679,7 @@ public abstract class OpModeRobot extends RobotBase { m_callbacks.addAll(m_activeOpModeCallbacks); } } else { - DriverStation.reportError("No OpMode found for mode " + modeId, false); + DriverStationErrors.reportError("No OpMode found for mode " + modeId, false); } } m_lastModeId = modeId; @@ -723,7 +726,7 @@ public abstract class OpModeRobot extends RobotBase { } // Call nonePeriodic when no opmode is selected - if (DriverStation.getOpModeId() == 0) { + if (RobotState.getOpModeId() == 0) { nonePeriodic(); m_watchdog.addEpoch("nonePeriodic()"); } @@ -767,7 +770,7 @@ public abstract class OpModeRobot extends RobotBase { } // Tell the DS that the robot is ready to be enabled - DriverStation.observeUserProgramStarting(); + DriverStationBackend.observeUserProgramStarting(); // Loop forever, calling the callback system which handles periodic functions while (true) { diff --git a/wpilibj/src/main/java/org/wpilib/framework/RobotBase.java b/wpilibj/src/main/java/org/wpilib/framework/RobotBase.java index f1f7394193..5bf286a833 100644 --- a/wpilibj/src/main/java/org/wpilib/framework/RobotBase.java +++ b/wpilibj/src/main/java/org/wpilib/framework/RobotBase.java @@ -6,9 +6,11 @@ package org.wpilib.framework; import java.util.Optional; import java.util.concurrent.locks.ReentrantLock; -import org.wpilib.driverstation.DriverStation; +import org.wpilib.driverstation.DriverStationErrors; +import org.wpilib.driverstation.RobotState; import org.wpilib.driverstation.UserControls; import org.wpilib.driverstation.UserControlsInstance; +import org.wpilib.driverstation.internal.DriverStationBackend; import org.wpilib.hardware.hal.HAL; import org.wpilib.hardware.hal.HALUtil; import org.wpilib.math.util.MathShared; @@ -52,7 +54,7 @@ public abstract class RobotBase implements AutoCloseable { @Override public void reportDriverStationError(String error) { - DriverStation.reportError(error, true); + DriverStationErrors.reportError(error, true); } @Override @@ -74,7 +76,7 @@ public abstract class RobotBase implements AutoCloseable { new MathShared() { @Override public void reportError(String error, StackTraceElement[] stackTrace) { - DriverStation.reportError(error, stackTrace); + DriverStationErrors.reportError(error, stackTrace); } @Override @@ -183,7 +185,7 @@ public abstract class RobotBase implements AutoCloseable { * @return True if the Robot is currently disabled by the Driver Station. */ public static boolean isDisabled() { - return DriverStation.isDisabled(); + return RobotState.isDisabled(); } /** @@ -192,7 +194,7 @@ public abstract class RobotBase implements AutoCloseable { * @return True if the Robot is currently enabled by the Driver Station. */ public static boolean isEnabled() { - return DriverStation.isEnabled(); + return RobotState.isEnabled(); } /** @@ -201,7 +203,7 @@ public abstract class RobotBase implements AutoCloseable { * @return True if the robot is currently operating Autonomously. */ public static boolean isAutonomous() { - return DriverStation.isAutonomous(); + return RobotState.isAutonomous(); } /** @@ -211,7 +213,7 @@ public abstract class RobotBase implements AutoCloseable { * @return True if the robot is currently operating autonomously while enabled. */ public static boolean isAutonomousEnabled() { - return DriverStation.isAutonomousEnabled(); + return RobotState.isAutonomousEnabled(); } /** @@ -220,7 +222,7 @@ public abstract class RobotBase implements AutoCloseable { * @return True if the robot is currently operating in Test mode. */ public static boolean isTest() { - return DriverStation.isTest(); + return RobotState.isTest(); } /** @@ -229,7 +231,7 @@ public abstract class RobotBase implements AutoCloseable { * @return True if the robot is currently operating in Test mode while enabled. */ public static boolean isTestEnabled() { - return DriverStation.isTestEnabled(); + return RobotState.isTestEnabled(); } /** @@ -239,7 +241,7 @@ public abstract class RobotBase implements AutoCloseable { * @return True if the robot is currently operating in Tele-Op mode. */ public static boolean isTeleop() { - return DriverStation.isTeleop(); + return RobotState.isTeleop(); } /** @@ -249,7 +251,7 @@ public abstract class RobotBase implements AutoCloseable { * @return True if the robot is currently operating in Tele-Op mode while enabled. */ public static boolean isTeleopEnabled() { - return DriverStation.isTeleopEnabled(); + return RobotState.isTeleopEnabled(); } /** @@ -260,7 +262,7 @@ public abstract class RobotBase implements AutoCloseable { * unique ID not added, so callers should be prepared to handle that case */ public static long getOpModeId() { - return DriverStation.getOpModeId(); + return RobotState.getOpModeId(); } /** @@ -271,7 +273,7 @@ public abstract class RobotBase implements AutoCloseable { * should be prepared to handle that case */ public static String getOpMode() { - return DriverStation.getOpMode(); + return RobotState.getOpMode(); } /** @@ -332,15 +334,15 @@ public abstract class RobotBase implements AutoCloseable { if (elements.length > 0) { robotName = elements[0].getClassName(); } - DriverStation.reportError( + DriverStationErrors.reportError( "Unhandled exception instantiating robot " + robotName + " " + throwable, elements); - DriverStation.reportError( + DriverStationErrors.reportError( "The robot program quit unexpectedly." + " This is usually due to a code error.\n" + " The above stacktrace can help determine where the error occurred.\n" + " See https://wpilib.org/stacktrace for more information.\n", false); - DriverStation.reportError("Could not instantiate robot " + robotName + "!", false); + DriverStationErrors.reportError("Could not instantiate robot " + robotName + "!", false); return; } @@ -356,7 +358,8 @@ public abstract class RobotBase implements AutoCloseable { if (cause != null) { throwable = cause; } - DriverStation.reportError("Unhandled exception: " + throwable, throwable.getStackTrace()); + DriverStationErrors.reportError( + "Unhandled exception: " + throwable, throwable.getStackTrace()); errorOnExit = true; } finally { m_runMutex.lock(); @@ -364,19 +367,20 @@ public abstract class RobotBase implements AutoCloseable { m_runMutex.unlock(); if (!suppressExitWarning) { // startCompetition never returns unless exception occurs.... - DriverStation.reportWarning( + DriverStationErrors.reportWarning( "The robot program quit unexpectedly." + " This is usually due to a code error.\n" + " The above stacktrace can help determine where the error occurred.\n" + " See https://wpilib.org/stacktrace for more information.", false); if (errorOnExit) { - DriverStation.reportError( + DriverStationErrors.reportError( "The startCompetition() method (or methods called by it) should have " + "handled the exception above.", false); } else { - DriverStation.reportError("Unexpected return from startCompetition() method.", false); + DriverStationErrors.reportError( + "Unexpected return from startCompetition() method.", false); } } } @@ -408,7 +412,7 @@ public abstract class RobotBase implements AutoCloseable { } // Force refresh DS data - DriverStation.refreshData(); + DriverStationBackend.refreshData(); HAL.reportUsage("Language", "Java"); HAL.reportUsage("WPILibVersion", WPILibVersion.Version); diff --git a/wpilibj/src/main/java/org/wpilib/framework/TimedRobot.java b/wpilibj/src/main/java/org/wpilib/framework/TimedRobot.java index ae73d1b3f5..446ee60fd4 100644 --- a/wpilibj/src/main/java/org/wpilib/framework/TimedRobot.java +++ b/wpilibj/src/main/java/org/wpilib/framework/TimedRobot.java @@ -6,7 +6,7 @@ package org.wpilib.framework; import static org.wpilib.units.Units.Seconds; -import org.wpilib.driverstation.DriverStation; +import org.wpilib.driverstation.internal.DriverStationBackend; import org.wpilib.hardware.hal.HAL; import org.wpilib.hardware.hal.NotifierJNI; import org.wpilib.internal.PeriodicPriorityQueue; @@ -86,7 +86,7 @@ public class TimedRobot extends IterativeRobotBase { // Tell the DS that the robot is ready to be enabled System.out.println("********** Robot program startup complete **********"); - DriverStation.observeUserProgramStarting(); + DriverStationBackend.observeUserProgramStarting(); // Loop forever, calling the appropriate mode-dependent function while (true) { diff --git a/wpilibj/src/main/java/org/wpilib/hardware/led/LEDPattern.java b/wpilibj/src/main/java/org/wpilib/hardware/led/LEDPattern.java index 6a5fae8c9b..cdad6c8dcf 100644 --- a/wpilibj/src/main/java/org/wpilib/hardware/led/LEDPattern.java +++ b/wpilibj/src/main/java/org/wpilib/hardware/led/LEDPattern.java @@ -13,7 +13,7 @@ import java.util.Map; import java.util.Objects; import java.util.function.BooleanSupplier; import java.util.function.DoubleSupplier; -import org.wpilib.driverstation.DriverStation; +import org.wpilib.driverstation.DriverStationErrors; import org.wpilib.hardware.hal.HAL; import org.wpilib.system.RobotController; import org.wpilib.units.collections.LongToObjectHashMap; @@ -576,13 +576,13 @@ public interface LEDPattern { HAL.reportUsage("LEDPattern", ""); if (steps.isEmpty()) { // no colors specified - DriverStation.reportWarning("Creating LED steps with no colors!", false); + DriverStationErrors.reportWarning("Creating LED steps with no colors!", false); return kOff; } if (steps.size() == 1 && steps.keySet().iterator().next().doubleValue() == 0) { // only one color specified, just show a static color - DriverStation.reportWarning("Creating LED steps with only one color!", false); + DriverStationErrors.reportWarning("Creating LED steps with only one color!", false); return solid(steps.values().iterator().next()); } @@ -638,13 +638,13 @@ public interface LEDPattern { HAL.reportUsage("LEDPattern", ""); if (colors.length == 0) { // Nothing to display - DriverStation.reportWarning("Creating a gradient with no colors!", false); + DriverStationErrors.reportWarning("Creating a gradient with no colors!", false); return kOff; } if (colors.length == 1) { // No gradients with one color - DriverStation.reportWarning("Creating a gradient with only one color!", false); + DriverStationErrors.reportWarning("Creating a gradient with only one color!", false); return solid(colors[0]); } diff --git a/wpilibj/src/main/java/org/wpilib/hardware/motor/MotorSafety.java b/wpilibj/src/main/java/org/wpilib/hardware/motor/MotorSafety.java index f80878a63d..055c31f99f 100644 --- a/wpilibj/src/main/java/org/wpilib/hardware/motor/MotorSafety.java +++ b/wpilibj/src/main/java/org/wpilib/hardware/motor/MotorSafety.java @@ -6,7 +6,8 @@ package org.wpilib.hardware.motor; import java.util.LinkedHashSet; import java.util.Set; -import org.wpilib.driverstation.DriverStation; +import org.wpilib.driverstation.DriverStationErrors; +import org.wpilib.driverstation.RobotState; import org.wpilib.hardware.hal.ControlWord; import org.wpilib.hardware.hal.DriverStationJNI; import org.wpilib.system.Timer; @@ -133,12 +134,12 @@ public abstract class MotorSafety { stopTime = m_stopTime; } - if (!enabled || DriverStation.isDisabled() || DriverStation.isTest()) { + if (!enabled || RobotState.isDisabled() || RobotState.isTest()) { return; } if (stopTime < Timer.getMonotonicTimestamp()) { - DriverStation.reportError( + DriverStationErrors.reportError( getDescription() + "... Output not updated often enough. See https://docs.wpilib.org/motorsafety for more information.", false); diff --git a/wpilibj/src/main/java/org/wpilib/internal/DriverStationModeThread.java b/wpilibj/src/main/java/org/wpilib/internal/DriverStationModeThread.java index ddffbf82da..1dff01040d 100644 --- a/wpilibj/src/main/java/org/wpilib/internal/DriverStationModeThread.java +++ b/wpilibj/src/main/java/org/wpilib/internal/DriverStationModeThread.java @@ -6,7 +6,7 @@ package org.wpilib.internal; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; -import org.wpilib.driverstation.DriverStation; +import org.wpilib.driverstation.internal.DriverStationBackend; import org.wpilib.hardware.hal.ControlWord; import org.wpilib.hardware.hal.DriverStationJNI; import org.wpilib.util.WPIUtilJNI; @@ -41,7 +41,7 @@ public class DriverStationModeThread implements AutoCloseable { if (!m_keepAlive.get()) { return; } - DriverStation.refreshData(); + DriverStationBackend.refreshData(); DriverStationJNI.observeUserProgram(m_userControlWord.get()); } } diff --git a/wpilibj/src/main/java/org/wpilib/simulation/DriverStationSim.java b/wpilibj/src/main/java/org/wpilib/simulation/DriverStationSim.java index 52c23eb722..f896f9ac02 100644 --- a/wpilibj/src/main/java/org/wpilib/simulation/DriverStationSim.java +++ b/wpilibj/src/main/java/org/wpilib/simulation/DriverStationSim.java @@ -5,7 +5,9 @@ package org.wpilib.simulation; import java.util.function.BiConsumer; -import org.wpilib.driverstation.DriverStation; +import org.wpilib.driverstation.MatchType; +import org.wpilib.driverstation.POVDirection; +import org.wpilib.driverstation.internal.DriverStationBackend; import org.wpilib.hardware.hal.AllianceStationID; import org.wpilib.hardware.hal.DriverStationJNI; import org.wpilib.hardware.hal.OpModeOption; @@ -321,7 +323,7 @@ public final class DriverStationSim { } DriverStationJNI.removeNewDataEventHandle(handle); WPIUtilJNI.destroyEvent(handle); - DriverStation.refreshData(); + DriverStationBackend.refreshData(); } /** @@ -392,7 +394,7 @@ public final class DriverStationSim { * @param pov The POV number * @param value the angle of the POV */ - public static void setJoystickPOV(int stick, int pov, DriverStation.POVDirection value) { + public static void setJoystickPOV(int stick, int pov, POVDirection value) { DriverStationDataJNI.setJoystickPOV(stick, pov, value.value); } @@ -523,7 +525,7 @@ public final class DriverStationSim { * * @param type the match type */ - public static void setMatchType(DriverStation.MatchType type) { + public static void setMatchType(MatchType type) { int matchType = switch (type) { case PRACTICE -> 1; diff --git a/wpilibj/src/main/java/org/wpilib/simulation/GenericHIDSim.java b/wpilibj/src/main/java/org/wpilib/simulation/GenericHIDSim.java index 27370faa2a..c9d61ac34d 100644 --- a/wpilibj/src/main/java/org/wpilib/simulation/GenericHIDSim.java +++ b/wpilibj/src/main/java/org/wpilib/simulation/GenericHIDSim.java @@ -5,8 +5,8 @@ package org.wpilib.simulation; import java.util.EnumSet; -import org.wpilib.driverstation.DriverStation; import org.wpilib.driverstation.GenericHID; +import org.wpilib.driverstation.POVDirection; /** Class to control a simulated generic joystick. */ public class GenericHIDSim { @@ -62,7 +62,7 @@ public class GenericHIDSim { * @param pov the POV to set * @param value the new value */ - public void setPOV(int pov, DriverStation.POVDirection value) { + public void setPOV(int pov, POVDirection value) { DriverStationSim.setJoystickPOV(m_port, pov, value); } @@ -71,7 +71,7 @@ public class GenericHIDSim { * * @param value the new value */ - public void setPOV(DriverStation.POVDirection value) { + public void setPOV(POVDirection value) { setPOV(0, value); } diff --git a/wpilibj/src/main/java/org/wpilib/system/DataLogManager.java b/wpilibj/src/main/java/org/wpilib/system/DataLogManager.java index 48f6fe0107..9353420f62 100644 --- a/wpilibj/src/main/java/org/wpilib/system/DataLogManager.java +++ b/wpilibj/src/main/java/org/wpilib/system/DataLogManager.java @@ -20,7 +20,11 @@ import org.wpilib.datalog.DataLogBackgroundWriter; import org.wpilib.datalog.FileLogger; import org.wpilib.datalog.IntegerLogEntry; import org.wpilib.datalog.StringLogEntry; -import org.wpilib.driverstation.DriverStation; +import org.wpilib.driverstation.DriverStationErrors; +import org.wpilib.driverstation.MatchState; +import org.wpilib.driverstation.MatchType; +import org.wpilib.driverstation.RobotState; +import org.wpilib.driverstation.internal.DriverStationBackend; import org.wpilib.framework.RobotBase; import org.wpilib.hardware.hal.HAL; import org.wpilib.networktables.NetworkTableInstance; @@ -326,7 +330,7 @@ public final class DataLogManager { } long length = file.length(); if (file.delete()) { - DriverStation.reportWarning("DataLogManager: Deleted " + file.getName(), false); + DriverStationErrors.reportWarning("DataLogManager: Deleted " + file.getName(), false); freeSpace += length; if (freeSpace >= FREE_SPACE_THRESHOLD) { break; @@ -337,7 +341,7 @@ public final class DataLogManager { } } } else if (freeSpace < 2 * FREE_SPACE_THRESHOLD) { - DriverStation.reportWarning( + DriverStationErrors.reportWarning( "DataLogManager: Log storage device has " + freeSpace / 1000000 + " MB of free space remaining! Logs will get deleted below " @@ -360,7 +364,7 @@ public final class DataLogManager { m_log, "systemTime", "{\"source\":\"DataLogManager\",\"format\":\"time_t_us\"}"); Event newDataEvent = new Event(); - DriverStation.provideRefreshedDataEventHandle(newDataEvent.getHandle()); + DriverStationBackend.provideRefreshedDataEventHandle(newDataEvent.getHandle()); while (!Thread.interrupted()) { boolean timedOut; try { @@ -390,7 +394,7 @@ public final class DataLogManager { if (!dsRenamed) { // track DS attach - if (DriverStation.isDSAttached()) { + if (RobotState.isDSAttached()) { dsAttachCount++; } else { dsAttachCount = 0; @@ -408,7 +412,7 @@ public final class DataLogManager { if (!fmsRenamed) { // track FMS attach - if (DriverStation.isFMSAttached()) { + if (RobotState.isFMSAttached()) { fmsAttachCount++; } else { fmsAttachCount = 0; @@ -416,8 +420,8 @@ public final class DataLogManager { if (fmsAttachCount > 250) { // 5 seconds // match info comes through TCP, so we need to double-check we've // actually received it - DriverStation.MatchType matchType = DriverStation.getMatchType(); - if (matchType != DriverStation.MatchType.NONE) { + MatchType matchType = MatchState.getMatchType(); + if (matchType != MatchType.NONE) { // rename per match info char matchTypeChar = switch (matchType) { @@ -430,10 +434,10 @@ public final class DataLogManager { "WPILIB_" + m_timeFormatter.format(LocalDateTime.now(m_utc)) + "_" - + DriverStation.getEventName() + + MatchState.getEventName() + "_" + matchTypeChar - + DriverStation.getMatchNumber() + + MatchState.getMatchNumber() + ".wpilog"); fmsRenamed = true; dsRenamed = true; // don't override FMS rename diff --git a/wpilibj/src/main/java/org/wpilib/system/Notifier.java b/wpilibj/src/main/java/org/wpilib/system/Notifier.java index 9f8cd4c030..5604ce1bd7 100644 --- a/wpilibj/src/main/java/org/wpilib/system/Notifier.java +++ b/wpilibj/src/main/java/org/wpilib/system/Notifier.java @@ -9,7 +9,7 @@ import static org.wpilib.util.ErrorMessages.requireNonNullParam; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.ReentrantLock; -import org.wpilib.driverstation.DriverStation; +import org.wpilib.driverstation.DriverStationErrors; import org.wpilib.hardware.hal.NotifierJNI; import org.wpilib.units.measure.Frequency; import org.wpilib.units.measure.Time; @@ -106,9 +106,9 @@ public class Notifier implements AutoCloseable { if (cause != null) { error = cause; } - DriverStation.reportError( + DriverStationErrors.reportError( "Unhandled exception in Notifier thread: " + error, error.getStackTrace()); - DriverStation.reportError( + DriverStationErrors.reportError( "The Runnable for this Notifier (or methods called by it) should have handled " + "the exception above.\n" + " The above stacktrace can help determine where the error occurred.\n" diff --git a/wpilibj/src/main/java/org/wpilib/system/Timer.java b/wpilibj/src/main/java/org/wpilib/system/Timer.java index b438150f48..5034595881 100644 --- a/wpilibj/src/main/java/org/wpilib/system/Timer.java +++ b/wpilibj/src/main/java/org/wpilib/system/Timer.java @@ -6,7 +6,7 @@ package org.wpilib.system; import static org.wpilib.units.Units.Seconds; -import org.wpilib.driverstation.DriverStation; +import org.wpilib.driverstation.MatchState; import org.wpilib.units.measure.Time; /** @@ -54,7 +54,7 @@ public class Timer { * @return Time remaining in current match period (auto or teleop) in seconds */ public static double getMatchTime() { - return DriverStation.getMatchTime(); + return MatchState.getMatchTime(); } /** diff --git a/wpilibj/src/main/java/org/wpilib/system/Tracer.java b/wpilibj/src/main/java/org/wpilib/system/Tracer.java index bdfdb9b609..e1c5026479 100644 --- a/wpilibj/src/main/java/org/wpilib/system/Tracer.java +++ b/wpilibj/src/main/java/org/wpilib/system/Tracer.java @@ -7,7 +7,7 @@ package org.wpilib.system; import java.util.HashMap; import java.util.Map; import java.util.function.Consumer; -import org.wpilib.driverstation.DriverStation; +import org.wpilib.driverstation.DriverStationErrors; /** * A class for keeping track of how much time it takes for different parts of code to execute. This @@ -60,7 +60,7 @@ public class Tracer { /** Prints list of epochs added so far and their times to the DriverStation. */ public void printEpochs() { - printEpochs(out -> DriverStation.reportWarning(out, false)); + printEpochs(out -> DriverStationErrors.reportWarning(out, false)); } /** diff --git a/wpilibj/src/main/java/org/wpilib/system/Watchdog.java b/wpilibj/src/main/java/org/wpilib/system/Watchdog.java index 1522c809df..7aa3f88d3b 100644 --- a/wpilibj/src/main/java/org/wpilib/system/Watchdog.java +++ b/wpilibj/src/main/java/org/wpilib/system/Watchdog.java @@ -9,7 +9,7 @@ import static org.wpilib.units.Units.Seconds; import java.io.Closeable; import java.util.PriorityQueue; import java.util.concurrent.locks.ReentrantLock; -import org.wpilib.driverstation.DriverStation; +import org.wpilib.driverstation.DriverStationErrors; import org.wpilib.hardware.hal.HALUtil; import org.wpilib.hardware.hal.NotifierJNI; import org.wpilib.units.measure.Time; @@ -263,7 +263,7 @@ public class Watchdog implements Closeable, Comparable { if (now - watchdog.m_lastTimeoutPrint > MIN_PRINT_PERIOD) { watchdog.m_lastTimeoutPrint = now; if (!watchdog.m_suppressTimeoutMessage) { - DriverStation.reportWarning( + DriverStationErrors.reportWarning( String.format("Watchdog not fed within %.6fs\n", watchdog.m_timeout), false); } } diff --git a/wpilibj/src/test/java/org/wpilib/driverstation/DriverStationTest.java b/wpilibj/src/test/java/org/wpilib/driverstation/DriverStationTest.java index 4ff56fe880..1287f9b38d 100644 --- a/wpilibj/src/test/java/org/wpilib/driverstation/DriverStationTest.java +++ b/wpilibj/src/test/java/org/wpilib/driverstation/DriverStationTest.java @@ -13,6 +13,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import org.wpilib.driverstation.internal.DriverStationBackend; import org.wpilib.simulation.DriverStationSim; class DriverStationTest { @@ -25,31 +26,31 @@ class DriverStationTest { DriverStationSim.notifyNewData(); - assertEquals(expected, DriverStation.isJoystickConnected(1)); + assertEquals(expected, DriverStationBackend.isJoystickConnected(1)); } @Test void getOpmodeIdReturnsZeroUntilUserProgramStarts() { DriverStationSim.setOpMode(0x1234); DriverStationSim.notifyNewData(); - assertEquals(0, DriverStation.getOpModeId()); + assertEquals(0, RobotState.getOpModeId()); - DriverStation.observeUserProgramStarting(); + DriverStationBackend.observeUserProgramStarting(); // need to manually mask because the upper eight bits include robot mode information - assertEquals(0x1234, DriverStation.getOpModeId() & 0xFFFF); + assertEquals(0x1234, RobotState.getOpModeId() & 0xFFFF); } @Test void getOpmodeReturnsEmptyStringUntilUserProgramStarts() { DriverStationSim.setOpMode(0x1234); DriverStationSim.notifyNewData(); - assertEquals("", DriverStation.getOpMode()); + assertEquals("", RobotState.getOpMode()); - DriverStation.observeUserProgramStarting(); + DriverStationBackend.observeUserProgramStarting(); // in Sim, the opmode string is just the stringified version of the opmode i64 "<0000...0000>" // we need to parse the string to get the // need to manually mask because the upper eight bits include robot mode information - String opmodeName = DriverStation.getOpMode(); + String opmodeName = RobotState.getOpMode(); assertEquals( "0x1234", String.format( @@ -71,8 +72,8 @@ class DriverStationTest { DriverStationSim.setFmsAttached(fms); DriverStationSim.notifyNewData(); - DriverStation.silenceJoystickConnectionWarning(silence); - assertEquals(expected, DriverStation.isJoystickConnectionWarningSilenced()); + DriverStationBackend.silenceJoystickConnectionWarning(silence); + assertEquals(expected, DriverStationBackend.isJoystickConnectionWarningSilenced()); } static Stream connectionWarningProvider() { @@ -86,7 +87,7 @@ class DriverStationTest { @AfterEach @SuppressWarnings("PMD.AvoidAccessibilityAlteration") void resetUserProgramFlag() throws ReflectiveOperationException { - var field = DriverStation.class.getDeclaredField("m_userProgramStarted"); + var field = DriverStationBackend.class.getDeclaredField("m_userProgramStarted"); field.setAccessible(true); field.set(null, false); } diff --git a/wpilibj/src/test/java/org/wpilib/framework/OpModeRobotTest.java b/wpilibj/src/test/java/org/wpilib/framework/OpModeRobotTest.java index 10820ccfce..482805336f 100644 --- a/wpilibj/src/test/java/org/wpilib/framework/OpModeRobotTest.java +++ b/wpilibj/src/test/java/org/wpilib/framework/OpModeRobotTest.java @@ -14,7 +14,7 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.parallel.ResourceLock; -import org.wpilib.driverstation.DriverStation; +import org.wpilib.driverstation.internal.DriverStationBackend; import org.wpilib.hardware.hal.RobotMode; import org.wpilib.opmode.OpMode; import org.wpilib.simulation.DriverStationSim; @@ -99,14 +99,14 @@ class OpModeRobotTest { @AfterEach void tearDown() { - DriverStation.clearOpModes(); + DriverStationBackend.clearOpModes(); SimHooks.resumeTiming(); } @AfterEach @SuppressWarnings("PMD.AvoidAccessibilityAlteration") void resetUserProgramFlag() throws ReflectiveOperationException { - var field = DriverStation.class.getDeclaredField("m_userProgramStarted"); + var field = DriverStationBackend.class.getDeclaredField("m_userProgramStarted"); field.setAccessible(true); field.set(null, false); } diff --git a/wpilibj/src/test/java/org/wpilib/hal/MatchInfoDataTest.java b/wpilibj/src/test/java/org/wpilib/hal/MatchInfoDataTest.java index 21df648a4a..cb29b26b87 100644 --- a/wpilibj/src/test/java/org/wpilib/hal/MatchInfoDataTest.java +++ b/wpilibj/src/test/java/org/wpilib/hal/MatchInfoDataTest.java @@ -8,7 +8,7 @@ import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; -import org.wpilib.driverstation.DriverStation.MatchType; +import org.wpilib.driverstation.MatchType; import org.wpilib.hardware.hal.DriverStationJNI; import org.wpilib.hardware.hal.MatchInfoData; import org.wpilib.hardware.hal.simulation.DriverStationDataJNI; diff --git a/wpilibj/src/test/java/org/wpilib/simulation/DriverStationSimTest.java b/wpilibj/src/test/java/org/wpilib/simulation/DriverStationSimTest.java index 7ccc6c3360..c6a6d4dcc7 100644 --- a/wpilibj/src/test/java/org/wpilib/simulation/DriverStationSimTest.java +++ b/wpilibj/src/test/java/org/wpilib/simulation/DriverStationSimTest.java @@ -11,7 +11,11 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; -import org.wpilib.driverstation.DriverStation; +import org.wpilib.driverstation.Alliance; +import org.wpilib.driverstation.MatchState; +import org.wpilib.driverstation.MatchType; +import org.wpilib.driverstation.RobotState; +import org.wpilib.driverstation.internal.DriverStationBackend; import org.wpilib.hardware.hal.AllianceStationID; import org.wpilib.hardware.hal.HAL; import org.wpilib.hardware.hal.RobotMode; @@ -25,13 +29,13 @@ class DriverStationSimTest { HAL.initialize(500, 0); DriverStationSim.resetData(); - assertFalse(DriverStation.isEnabled()); + assertFalse(RobotState.isEnabled()); BooleanCallback callback = new BooleanCallback(); try (CallbackStore cb = DriverStationSim.registerEnabledCallback(callback, false)) { DriverStationSim.setEnabled(true); DriverStationSim.notifyNewData(); assertTrue(DriverStationSim.getEnabled()); - assertTrue(DriverStation.isEnabled()); + assertTrue(RobotState.isEnabled()); assertTrue(callback.wasTriggered()); assertTrue(callback.getSetValue()); } @@ -42,14 +46,14 @@ class DriverStationSimTest { HAL.initialize(500, 0); DriverStationSim.resetData(); - assertFalse(DriverStation.isAutonomous()); + assertFalse(RobotState.isAutonomous()); EnumCallback callback = new EnumCallback(); try (CallbackStore cb = DriverStationSim.registerRobotModeCallback(callback, false)) { DriverStationSim.setRobotMode(RobotMode.AUTONOMOUS); DriverStationSim.notifyNewData(); assertEquals(RobotMode.AUTONOMOUS, DriverStationSim.getRobotMode()); - assertTrue(DriverStation.isAutonomous()); - assertEquals(RobotMode.AUTONOMOUS, DriverStation.getRobotMode()); + assertTrue(RobotState.isAutonomous()); + assertEquals(RobotMode.AUTONOMOUS, RobotState.getRobotMode()); assertTrue(callback.wasTriggered()); assertEquals(RobotMode.AUTONOMOUS.getValue(), callback.getSetValue()); } @@ -60,14 +64,14 @@ class DriverStationSimTest { HAL.initialize(500, 0); DriverStationSim.resetData(); - assertFalse(DriverStation.isTest()); + assertFalse(RobotState.isTest()); EnumCallback callback = new EnumCallback(); try (CallbackStore cb = DriverStationSim.registerRobotModeCallback(callback, false)) { DriverStationSim.setRobotMode(RobotMode.TEST); DriverStationSim.notifyNewData(); assertEquals(RobotMode.TEST, DriverStationSim.getRobotMode()); - assertTrue(DriverStation.isTest()); - assertEquals(RobotMode.TEST, DriverStation.getRobotMode()); + assertTrue(RobotState.isTest()); + assertEquals(RobotMode.TEST, RobotState.getRobotMode()); assertTrue(callback.wasTriggered()); assertEquals(RobotMode.TEST.getValue(), callback.getSetValue()); } @@ -78,13 +82,13 @@ class DriverStationSimTest { HAL.initialize(500, 0); DriverStationSim.resetData(); - assertFalse(DriverStation.isEStopped()); + assertFalse(RobotState.isEStopped()); BooleanCallback callback = new BooleanCallback(); try (CallbackStore cb = DriverStationSim.registerEStopCallback(callback, false)) { DriverStationSim.setEStop(true); DriverStationSim.notifyNewData(); assertTrue(DriverStationSim.getEStop()); - assertTrue(DriverStation.isEStopped()); + assertTrue(RobotState.isEStopped()); assertTrue(callback.wasTriggered()); assertTrue(callback.getSetValue()); } @@ -95,13 +99,13 @@ class DriverStationSimTest { HAL.initialize(500, 0); DriverStationSim.resetData(); - assertFalse(DriverStation.isFMSAttached()); + assertFalse(RobotState.isFMSAttached()); BooleanCallback callback = new BooleanCallback(); try (CallbackStore cb = DriverStationSim.registerFmsAttachedCallback(callback, false)) { DriverStationSim.setFmsAttached(true); DriverStationSim.notifyNewData(); assertTrue(DriverStationSim.getFmsAttached()); - assertTrue(DriverStation.isFMSAttached()); + assertTrue(RobotState.isFMSAttached()); assertTrue(callback.wasTriggered()); assertTrue(callback.getSetValue()); } @@ -111,20 +115,20 @@ class DriverStationSimTest { void testDsAttached() { HAL.initialize(500, 0); DriverStationSim.resetData(); - DriverStation.refreshData(); + DriverStationBackend.refreshData(); assertFalse(DriverStationSim.getDsAttached()); - assertFalse(DriverStation.isDSAttached()); + assertFalse(RobotState.isDSAttached()); DriverStationSim.notifyNewData(); assertTrue(DriverStationSim.getDsAttached()); - assertTrue(DriverStation.isDSAttached()); + assertTrue(RobotState.isDSAttached()); BooleanCallback callback = new BooleanCallback(); try (CallbackStore cb = DriverStationSim.registerDsAttachedCallback(callback, false)) { DriverStationSim.setDsAttached(false); - DriverStation.refreshData(); + DriverStationBackend.refreshData(); assertFalse(DriverStationSim.getDsAttached()); - assertFalse(DriverStation.isDSAttached()); + assertFalse(RobotState.isDSAttached()); assertTrue(callback.wasTriggered()); assertFalse(callback.getSetValue()); } @@ -146,8 +150,8 @@ class DriverStationSimTest { DriverStationSim.setAllianceStationId(allianceStation); DriverStationSim.notifyNewData(); assertEquals(allianceStation, DriverStationSim.getAllianceStationId()); - assertFalse(DriverStation.getAlliance().isPresent()); - assertFalse(DriverStation.getLocation().isPresent()); + assertFalse(MatchState.getAlliance().isPresent()); + assertFalse(MatchState.getLocation().isPresent()); assertTrue(callback.wasTriggered()); assertEquals(allianceStation.ordinal(), callback.getSetValue()); @@ -156,8 +160,8 @@ class DriverStationSimTest { DriverStationSim.setAllianceStationId(allianceStation); DriverStationSim.notifyNewData(); assertEquals(allianceStation, DriverStationSim.getAllianceStationId()); - assertEquals(DriverStation.Alliance.BLUE, DriverStation.getAlliance().get()); - assertEquals(1, DriverStation.getLocation().getAsInt()); + assertEquals(Alliance.BLUE, MatchState.getAlliance().get()); + assertEquals(1, MatchState.getLocation().getAsInt()); assertTrue(callback.wasTriggered()); assertEquals(allianceStation.ordinal(), callback.getSetValue()); @@ -166,8 +170,8 @@ class DriverStationSimTest { DriverStationSim.setAllianceStationId(allianceStation); DriverStationSim.notifyNewData(); assertEquals(allianceStation, DriverStationSim.getAllianceStationId()); - assertEquals(DriverStation.Alliance.BLUE, DriverStation.getAlliance().get()); - assertEquals(2, DriverStation.getLocation().getAsInt()); + assertEquals(Alliance.BLUE, MatchState.getAlliance().get()); + assertEquals(2, MatchState.getLocation().getAsInt()); assertTrue(callback.wasTriggered()); assertEquals(allianceStation.ordinal(), callback.getSetValue()); @@ -176,8 +180,8 @@ class DriverStationSimTest { DriverStationSim.setAllianceStationId(allianceStation); DriverStationSim.notifyNewData(); assertEquals(allianceStation, DriverStationSim.getAllianceStationId()); - assertEquals(DriverStation.Alliance.BLUE, DriverStation.getAlliance().get()); - assertEquals(3, DriverStation.getLocation().getAsInt()); + assertEquals(Alliance.BLUE, MatchState.getAlliance().get()); + assertEquals(3, MatchState.getLocation().getAsInt()); assertTrue(callback.wasTriggered()); assertEquals(allianceStation.ordinal(), callback.getSetValue()); @@ -186,8 +190,8 @@ class DriverStationSimTest { DriverStationSim.setAllianceStationId(allianceStation); DriverStationSim.notifyNewData(); assertEquals(allianceStation, DriverStationSim.getAllianceStationId()); - assertEquals(DriverStation.Alliance.RED, DriverStation.getAlliance().get()); - assertEquals(1, DriverStation.getLocation().getAsInt()); + assertEquals(Alliance.RED, MatchState.getAlliance().get()); + assertEquals(1, MatchState.getLocation().getAsInt()); assertTrue(callback.wasTriggered()); assertEquals(allianceStation.ordinal(), callback.getSetValue()); @@ -196,8 +200,8 @@ class DriverStationSimTest { DriverStationSim.setAllianceStationId(allianceStation); DriverStationSim.notifyNewData(); assertEquals(allianceStation, DriverStationSim.getAllianceStationId()); - assertEquals(DriverStation.Alliance.RED, DriverStation.getAlliance().get()); - assertEquals(2, DriverStation.getLocation().getAsInt()); + assertEquals(Alliance.RED, MatchState.getAlliance().get()); + assertEquals(2, MatchState.getLocation().getAsInt()); assertTrue(callback.wasTriggered()); assertEquals(allianceStation.ordinal(), callback.getSetValue()); @@ -206,22 +210,22 @@ class DriverStationSimTest { DriverStationSim.setAllianceStationId(allianceStation); DriverStationSim.notifyNewData(); assertEquals(allianceStation, DriverStationSim.getAllianceStationId()); - assertEquals(DriverStation.Alliance.RED, DriverStation.getAlliance().get()); - assertEquals(3, DriverStation.getLocation().getAsInt()); + assertEquals(Alliance.RED, MatchState.getAlliance().get()); + assertEquals(3, MatchState.getLocation().getAsInt()); assertTrue(callback.wasTriggered()); assertEquals(allianceStation.ordinal(), callback.getSetValue()); } } @ParameterizedTest - @EnumSource(DriverStation.MatchType.class) - void testMatchType(DriverStation.MatchType matchType) { + @EnumSource(MatchType.class) + void testMatchType(MatchType matchType) { HAL.initialize(500, 0); DriverStationSim.resetData(); DriverStationSim.setMatchType(matchType); DriverStationSim.notifyNewData(); - assertEquals(matchType, DriverStation.getMatchType()); + assertEquals(matchType, MatchState.getMatchType()); } @Test @@ -231,7 +235,7 @@ class DriverStationSimTest { DriverStationSim.setReplayNumber(4); DriverStationSim.notifyNewData(); - assertEquals(4, DriverStation.getReplayNumber()); + assertEquals(4, MatchState.getReplayNumber()); } @Test @@ -241,7 +245,7 @@ class DriverStationSimTest { DriverStationSim.setMatchNumber(3); DriverStationSim.notifyNewData(); - assertEquals(3, DriverStation.getMatchNumber()); + assertEquals(3, MatchState.getMatchNumber()); } @Test @@ -254,8 +258,8 @@ class DriverStationSimTest { final double testTime = 19.174; DriverStationSim.setMatchTime(testTime); DriverStationSim.notifyNewData(); - assertEquals(testTime, DriverStationSim.getMatchTime()); - assertEquals(testTime, DriverStation.getMatchTime()); + assertEquals(testTime, MatchState.getMatchTime()); + assertEquals(testTime, MatchState.getMatchTime()); assertTrue(callback.wasTriggered()); assertEquals(testTime, callback.getSetValue()); } @@ -269,7 +273,7 @@ class DriverStationSimTest { final String message = "Hello"; DriverStationSim.setGameData(message); DriverStationSim.notifyNewData(); - var gameData = DriverStation.getGameData(); + var gameData = MatchState.getGameData(); assertTrue(gameData.isPresent()); assertEquals(message, gameData.get()); } @@ -281,7 +285,7 @@ class DriverStationSimTest { DriverStationSim.setGameData(""); DriverStationSim.notifyNewData(); - assertTrue(DriverStation.getGameData().isEmpty()); + assertTrue(MatchState.getGameData().isEmpty()); } @Test @@ -291,7 +295,7 @@ class DriverStationSimTest { DriverStationSim.setGameData(null); DriverStationSim.notifyNewData(); - assertTrue(DriverStation.getGameData().isEmpty()); + assertTrue(MatchState.getGameData().isEmpty()); } @Test @@ -302,6 +306,6 @@ class DriverStationSimTest { final String message = "The Best Event"; DriverStationSim.setEventName(message); DriverStationSim.notifyNewData(); - assertEquals(message, DriverStation.getEventName()); + assertEquals(message, MatchState.getEventName()); } } diff --git a/wpilibjExamples/src/main/java/org/wpilib/snippets/digitalcommunication/Robot.java b/wpilibjExamples/src/main/java/org/wpilib/snippets/digitalcommunication/Robot.java index e1d7867ab4..6fb792157c 100644 --- a/wpilibjExamples/src/main/java/org/wpilib/snippets/digitalcommunication/Robot.java +++ b/wpilibjExamples/src/main/java/org/wpilib/snippets/digitalcommunication/Robot.java @@ -5,7 +5,9 @@ package org.wpilib.snippets.digitalcommunication; import java.util.Optional; -import org.wpilib.driverstation.DriverStation; +import org.wpilib.driverstation.Alliance; +import org.wpilib.driverstation.MatchState; +import org.wpilib.driverstation.RobotState; import org.wpilib.framework.TimedRobot; import org.wpilib.hardware.discrete.DigitalOutput; @@ -28,22 +30,22 @@ public class Robot extends TimedRobot { @Override public void robotPeriodic() { boolean setAlliance = false; - Optional alliance = DriverStation.getAlliance(); + Optional alliance = MatchState.getAlliance(); if (alliance.isPresent()) { - setAlliance = alliance.get() == DriverStation.Alliance.RED; + setAlliance = alliance.get() == Alliance.RED; } // pull alliance port high if on red alliance, pull low if on blue alliance m_allianceOutput.set(setAlliance); // pull enabled port high if enabled, low if disabled - m_enabledOutput.set(DriverStation.isEnabled()); + m_enabledOutput.set(RobotState.isEnabled()); // pull auto port high if in autonomous, low if in teleop (or disabled) - m_autonomousOutput.set(DriverStation.isAutonomous()); + m_autonomousOutput.set(RobotState.isAutonomous()); // pull alert port high if match time remaining is between 30 and 25 seconds - var matchTime = DriverStation.getMatchTime(); + var matchTime = MatchState.getMatchTime(); m_alertOutput.set(matchTime <= 30 && matchTime >= 25); } diff --git a/wpilibjExamples/src/main/java/org/wpilib/snippets/i2ccommunication/Robot.java b/wpilibjExamples/src/main/java/org/wpilib/snippets/i2ccommunication/Robot.java index fc64c7de54..1512f9a735 100644 --- a/wpilibjExamples/src/main/java/org/wpilib/snippets/i2ccommunication/Robot.java +++ b/wpilibjExamples/src/main/java/org/wpilib/snippets/i2ccommunication/Robot.java @@ -5,7 +5,9 @@ package org.wpilib.snippets.i2ccommunication; import java.util.Optional; -import org.wpilib.driverstation.DriverStation; +import org.wpilib.driverstation.Alliance; +import org.wpilib.driverstation.MatchState; +import org.wpilib.driverstation.RobotState; import org.wpilib.framework.TimedRobot; import org.wpilib.hardware.bus.I2C; import org.wpilib.hardware.bus.I2C.Port; @@ -51,16 +53,16 @@ public class Robot extends TimedRobot { StringBuilder stateMessage = new StringBuilder(6); String allianceString = "U"; - Optional alliance = DriverStation.getAlliance(); + Optional alliance = MatchState.getAlliance(); if (alliance.isPresent()) { - allianceString = alliance.get() == DriverStation.Alliance.RED ? "R" : "B"; + allianceString = alliance.get() == Alliance.RED ? "R" : "B"; } stateMessage .append(allianceString) - .append(DriverStation.isEnabled() ? "E" : "D") - .append(DriverStation.isAutonomous() ? "A" : "T") - .append(String.format("%03d", (int) DriverStation.getMatchTime())); + .append(RobotState.isEnabled() ? "E" : "D") + .append(RobotState.isAutonomous() ? "A" : "T") + .append(String.format("%03d", (int) MatchState.getMatchTime())); writeString(stateMessage.toString()); } diff --git a/wpilibjExamples/src/main/java/org/wpilib/templates/educational/EducationalRobot.java b/wpilibjExamples/src/main/java/org/wpilib/templates/educational/EducationalRobot.java index 62cde21db3..e3b57d5bd3 100644 --- a/wpilibjExamples/src/main/java/org/wpilib/templates/educational/EducationalRobot.java +++ b/wpilibjExamples/src/main/java/org/wpilib/templates/educational/EducationalRobot.java @@ -4,7 +4,8 @@ package org.wpilib.templates.educational; -import org.wpilib.driverstation.DriverStation; +import org.wpilib.driverstation.RobotState; +import org.wpilib.driverstation.internal.DriverStationBackend; import org.wpilib.framework.RobotBase; import org.wpilib.hardware.hal.ControlWord; import org.wpilib.hardware.hal.RobotMode; @@ -36,23 +37,23 @@ public class EducationalRobot extends RobotBase { @Override public void startCompetition() { // Create an opmode per robot mode - DriverStation.addOpMode(RobotMode.AUTONOMOUS, "Auto"); - DriverStation.addOpMode(RobotMode.TELEOPERATED, "Teleop"); - DriverStation.addOpMode(RobotMode.TEST, "Test"); - DriverStation.publishOpModes(); + RobotState.addOpMode(RobotMode.AUTONOMOUS, "Auto"); + RobotState.addOpMode(RobotMode.TELEOPERATED, "Teleop"); + RobotState.addOpMode(RobotMode.TEST, "Test"); + RobotState.publishOpModes(); final ControlWord word = new ControlWord(); DriverStationModeThread modeThread = new DriverStationModeThread(word); int event = WPIUtilJNI.makeEvent(false, false); - DriverStation.provideRefreshedDataEventHandle(event); + DriverStationBackend.provideRefreshedDataEventHandle(event); // Tell the DS that the robot is ready to be enabled - DriverStation.observeUserProgramStarting(); + DriverStationBackend.observeUserProgramStarting(); while (!Thread.currentThread().isInterrupted() && !m_exit) { - DriverStation.refreshControlWordFromCache(word); + DriverStationBackend.refreshControlWordFromCache(word); modeThread.inControl(word); if (isDisabled()) { disabled(); @@ -93,7 +94,7 @@ public class EducationalRobot extends RobotBase { } } - DriverStation.removeRefreshedDataEventHandle(event); + DriverStationBackend.removeRefreshedDataEventHandle(event); modeThread.close(); } diff --git a/wpilibjExamples/src/main/java/org/wpilib/templates/robotbaseskeleton/Robot.java b/wpilibjExamples/src/main/java/org/wpilib/templates/robotbaseskeleton/Robot.java index 79e3b9f2e9..965d7e5f85 100644 --- a/wpilibjExamples/src/main/java/org/wpilib/templates/robotbaseskeleton/Robot.java +++ b/wpilibjExamples/src/main/java/org/wpilib/templates/robotbaseskeleton/Robot.java @@ -4,7 +4,8 @@ package org.wpilib.templates.robotbaseskeleton; -import org.wpilib.driverstation.DriverStation; +import org.wpilib.driverstation.RobotState; +import org.wpilib.driverstation.internal.DriverStationBackend; import org.wpilib.framework.RobotBase; import org.wpilib.hardware.hal.ControlWord; import org.wpilib.hardware.hal.RobotMode; @@ -31,23 +32,23 @@ public class Robot extends RobotBase { @Override public void startCompetition() { // Create an opmode per robot mode - DriverStation.addOpMode(RobotMode.AUTONOMOUS, "Auto"); - DriverStation.addOpMode(RobotMode.TELEOPERATED, "Teleop"); - DriverStation.addOpMode(RobotMode.TEST, "Test"); - DriverStation.publishOpModes(); + RobotState.addOpMode(RobotMode.AUTONOMOUS, "Auto"); + RobotState.addOpMode(RobotMode.TELEOPERATED, "Teleop"); + RobotState.addOpMode(RobotMode.TEST, "Test"); + RobotState.publishOpModes(); final ControlWord word = new ControlWord(); DriverStationModeThread modeThread = new DriverStationModeThread(word); int event = WPIUtilJNI.makeEvent(false, false); - DriverStation.provideRefreshedDataEventHandle(event); + DriverStationBackend.provideRefreshedDataEventHandle(event); // Tell the DS that the robot is ready to be enabled - DriverStation.observeUserProgramStarting(); + DriverStationBackend.observeUserProgramStarting(); while (!Thread.currentThread().isInterrupted() && !m_exit) { - DriverStation.refreshControlWordFromCache(word); + DriverStationBackend.refreshControlWordFromCache(word); modeThread.inControl(word); if (isDisabled()) { disabled(); @@ -88,7 +89,7 @@ public class Robot extends RobotBase { } } - DriverStation.removeRefreshedDataEventHandle(event); + DriverStationBackend.removeRefreshedDataEventHandle(event); modeThread.close(); } diff --git a/wpilibjExamples/src/main/java/org/wpilib/templates/romieducational/EducationalRobot.java b/wpilibjExamples/src/main/java/org/wpilib/templates/romieducational/EducationalRobot.java index f1c6af7daa..a549f66dc4 100644 --- a/wpilibjExamples/src/main/java/org/wpilib/templates/romieducational/EducationalRobot.java +++ b/wpilibjExamples/src/main/java/org/wpilib/templates/romieducational/EducationalRobot.java @@ -4,7 +4,8 @@ package org.wpilib.templates.romieducational; -import org.wpilib.driverstation.DriverStation; +import org.wpilib.driverstation.RobotState; +import org.wpilib.driverstation.internal.DriverStationBackend; import org.wpilib.framework.RobotBase; import org.wpilib.hardware.hal.ControlWord; import org.wpilib.hardware.hal.RobotMode; @@ -36,23 +37,23 @@ public class EducationalRobot extends RobotBase { @Override public void startCompetition() { // Create an opmode per robot mode - DriverStation.addOpMode(RobotMode.AUTONOMOUS, "Auto"); - DriverStation.addOpMode(RobotMode.TELEOPERATED, "Teleop"); - DriverStation.addOpMode(RobotMode.TEST, "Test"); - DriverStation.publishOpModes(); + RobotState.addOpMode(RobotMode.AUTONOMOUS, "Auto"); + RobotState.addOpMode(RobotMode.TELEOPERATED, "Teleop"); + RobotState.addOpMode(RobotMode.TEST, "Test"); + RobotState.publishOpModes(); final ControlWord word = new ControlWord(); DriverStationModeThread modeThread = new DriverStationModeThread(word); int event = WPIUtilJNI.makeEvent(false, false); - DriverStation.provideRefreshedDataEventHandle(event); + DriverStationBackend.provideRefreshedDataEventHandle(event); // Tell the DS that the robot is ready to be enabled - DriverStation.observeUserProgramStarting(); + DriverStationBackend.observeUserProgramStarting(); while (!Thread.currentThread().isInterrupted() && !m_exit) { - DriverStation.refreshControlWordFromCache(word); + DriverStationBackend.refreshControlWordFromCache(word); modeThread.inControl(word); if (isDisabled()) { disabled(); @@ -93,7 +94,7 @@ public class EducationalRobot extends RobotBase { } } - DriverStation.removeRefreshedDataEventHandle(event); + DriverStationBackend.removeRefreshedDataEventHandle(event); modeThread.close(); } diff --git a/wpilibjExamples/src/main/java/org/wpilib/templates/xrpeducational/EducationalRobot.java b/wpilibjExamples/src/main/java/org/wpilib/templates/xrpeducational/EducationalRobot.java index 41f97852ad..96b83978dd 100644 --- a/wpilibjExamples/src/main/java/org/wpilib/templates/xrpeducational/EducationalRobot.java +++ b/wpilibjExamples/src/main/java/org/wpilib/templates/xrpeducational/EducationalRobot.java @@ -4,7 +4,8 @@ package org.wpilib.templates.xrpeducational; -import org.wpilib.driverstation.DriverStation; +import org.wpilib.driverstation.RobotState; +import org.wpilib.driverstation.internal.DriverStationBackend; import org.wpilib.framework.RobotBase; import org.wpilib.hardware.hal.ControlWord; import org.wpilib.hardware.hal.RobotMode; @@ -36,23 +37,23 @@ public class EducationalRobot extends RobotBase { @Override public void startCompetition() { // Create an opmode per robot mode - DriverStation.addOpMode(RobotMode.AUTONOMOUS, "Auto"); - DriverStation.addOpMode(RobotMode.TELEOPERATED, "Teleop"); - DriverStation.addOpMode(RobotMode.TEST, "Test"); - DriverStation.publishOpModes(); + RobotState.addOpMode(RobotMode.AUTONOMOUS, "Auto"); + RobotState.addOpMode(RobotMode.TELEOPERATED, "Teleop"); + RobotState.addOpMode(RobotMode.TEST, "Test"); + RobotState.publishOpModes(); final ControlWord word = new ControlWord(); DriverStationModeThread modeThread = new DriverStationModeThread(word); int event = WPIUtilJNI.makeEvent(false, false); - DriverStation.provideRefreshedDataEventHandle(event); + DriverStationBackend.provideRefreshedDataEventHandle(event); // Tell the DS that the robot is ready to be enabled - DriverStation.observeUserProgramStarting(); + DriverStationBackend.observeUserProgramStarting(); while (!Thread.currentThread().isInterrupted() && !m_exit) { - DriverStation.refreshControlWordFromCache(word); + DriverStationBackend.refreshControlWordFromCache(word); modeThread.inControl(word); if (isDisabled()) { disabled(); @@ -93,7 +94,7 @@ public class EducationalRobot extends RobotBase { } } - DriverStation.removeRefreshedDataEventHandle(event); + DriverStationBackend.removeRefreshedDataEventHandle(event); modeThread.close(); } diff --git a/wpilibjExamples/src/test/java/org/wpilib/snippets/i2ccommunication/I2CCommunicationTest.java b/wpilibjExamples/src/test/java/org/wpilib/snippets/i2ccommunication/I2CCommunicationTest.java index 7e6d36d17c..f2313df886 100644 --- a/wpilibjExamples/src/test/java/org/wpilib/snippets/i2ccommunication/I2CCommunicationTest.java +++ b/wpilibjExamples/src/test/java/org/wpilib/snippets/i2ccommunication/I2CCommunicationTest.java @@ -17,7 +17,7 @@ import org.junit.jupiter.api.parallel.ResourceLock; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; import org.junit.jupiter.params.provider.ValueSource; -import org.wpilib.driverstation.DriverStation; +import org.wpilib.driverstation.MatchState; import org.wpilib.hardware.hal.AllianceStationID; import org.wpilib.hardware.hal.HAL; import org.wpilib.hardware.hal.RobotMode; @@ -126,7 +126,7 @@ class I2CCommunicationTest { SimHooks.stepTiming(0.02); String str = assertTimeoutPreemptively(Duration.ofMillis(20L), () -> m_future.get()); - String expected = String.format("%03d", (int) DriverStation.getMatchTime()); + String expected = String.format("%03d", (int) MatchState.getMatchTime()); assertEquals(expected, str.substring(3)); }