[hal,wpilib,cmd] Update POVs to use enums (#7978)

This commit is contained in:
Joseph Eng
2025-06-29 18:32:26 -07:00
committed by GitHub
parent e13d237390
commit f55564729b
30 changed files with 538 additions and 378 deletions

View File

@@ -14,6 +14,7 @@ import edu.wpi.first.hal.ControlWord;
import edu.wpi.first.hal.DriverStationJNI;
import edu.wpi.first.hal.HAL;
import edu.wpi.first.hal.MatchInfoData;
import edu.wpi.first.math.geometry.Rotation2d;
import edu.wpi.first.networktables.BooleanPublisher;
import edu.wpi.first.networktables.IntegerPublisher;
import edu.wpi.first.networktables.NetworkTableInstance;
@@ -89,6 +90,79 @@ public final class DriverStation {
Elimination
}
/** A controller POV direction. */
public enum POVDirection {
/** POV center. */
Center(0x00),
/** POV up. */
Up(0x01),
/** POV up right. */
UpRight(0x01 | 0x02),
/** POV right. */
Right(0x02),
/** POV down right. */
DownRight(0x02 | 0x04),
/** POV down. */
Down(0x04),
/** POV down left. */
DownLeft(0x04 | 0x08),
/** POV left. */
Left(0x08),
/** POV up left. */
UpLeft(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<Rotation2d> getAngle() {
return switch (this) {
case Center -> Optional.empty();
case Up -> Optional.of(Rotation2d.fromDegrees(0));
case UpRight -> Optional.of(Rotation2d.fromDegrees(45));
case Right -> Optional.of(Rotation2d.fromDegrees(90));
case DownRight -> Optional.of(Rotation2d.fromDegrees(135));
case Down -> Optional.of(Rotation2d.fromDegrees(180));
case DownLeft -> Optional.of(Rotation2d.fromDegrees(225));
case Left -> Optional.of(Rotation2d.fromDegrees(270));
case UpLeft -> Optional.of(Rotation2d.fromDegrees(315));
};
}
}
private static final double JOYSTICK_UNPLUGGED_MESSAGE_INTERVAL = 1.0;
private static double m_nextMessageTime;
@@ -674,9 +748,9 @@ public final class DriverStation {
*
* @param stick The joystick to read.
* @param pov The POV to read.
* @return the angle of the POV in degrees, or -1 if the POV is not pressed.
* @return the angle of the POV.
*/
public static int getStickPOV(int stick, int 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");
}
@@ -687,7 +761,7 @@ public final class DriverStation {
m_cacheDataMutex.lock();
try {
if (pov < m_joystickPOVs[stick].m_count) {
return m_joystickPOVs[stick].m_povs[pov];
return POVDirection.of(m_joystickPOVs[stick].m_povs[pov]);
}
} finally {
m_cacheDataMutex.unlock();
@@ -699,7 +773,7 @@ public final class DriverStation {
+ " on port "
+ stick
+ " not available, check if controller is plugged in");
return -1;
return POVDirection.Center;
}
/**

View File

@@ -7,6 +7,7 @@ package edu.wpi.first.wpilibj;
import edu.wpi.first.hal.DriverStationJNI;
import edu.wpi.first.math.MathUtil;
import edu.wpi.first.math.Pair;
import edu.wpi.first.wpilibj.DriverStation.POVDirection;
import edu.wpi.first.wpilibj.event.BooleanEvent;
import edu.wpi.first.wpilibj.event.EventLoop;
import java.util.HashMap;
@@ -183,150 +184,138 @@ public class GenericHID {
}
/**
* Get the angle in degrees of a POV on the HID.
*
* <p>The POV angles start at 0 in the up direction, and increase clockwise (e.g. right is 90,
* upper-left is 315).
* Get the angle of a POV on the HID.
*
* @param pov The index of the POV to read (starting at 0). Defaults to 0.
* @return the angle of the POV in degrees, or -1 if the POV is not pressed.
* @return the angle of the POV.
*/
public int getPOV(int pov) {
public POVDirection getPOV(int pov) {
return DriverStation.getStickPOV(m_port, pov);
}
/**
* Get the angle in degrees of the default POV (index 0) on the HID.
* Get the angle of the default POV (index 0) on the HID.
*
* <p>The POV angles start at 0 in the up direction, and increase clockwise (e.g. right is 90,
* upper-left is 315).
*
* @return the angle of the POV in degrees, or -1 if the POV is not pressed.
* @return the angle of the POV.
*/
public int getPOV() {
public POVDirection getPOV() {
return getPOV(0);
}
/**
* Constructs a BooleanEvent instance based around this angle of a POV on the HID.
*
* <p>The POV angles start at 0 in the up direction, and increase clockwise (eg right is 90,
* upper-left is 315).
*
* @param angle POV angle in degrees, or -1 for the center / not pressed.
* @param angle POV angle.
* @param loop the event loop instance to attach the event to.
* @return a BooleanEvent instance based around this angle of a POV on the HID.
*/
public BooleanEvent pov(int angle, EventLoop loop) {
public BooleanEvent pov(POVDirection angle, EventLoop loop) {
return pov(0, angle, loop);
}
/**
* Constructs a BooleanEvent instance based around this angle of a POV on the HID.
*
* <p>The POV angles start at 0 in the up direction, and increase clockwise (e.g. right is 90,
* upper-left is 315).
*
* @param pov index of the POV to read (starting at 0). Defaults to 0.
* @param angle POV angle in degrees, or -1 for the center / not pressed.
* @param angle POV angle.
* @param loop the event loop instance to attach the event to.
* @return a BooleanEvent instance based around this angle of a POV on the HID.
*/
public BooleanEvent pov(int pov, int angle, EventLoop loop) {
public BooleanEvent pov(int pov, POVDirection angle, EventLoop loop) {
synchronized (m_povCache) {
var cache = m_povCache.computeIfAbsent(loop, k -> new HashMap<>());
// angle can be -1, so use 3600 instead of 360
// angle.value is a 4 bit bitfield
return cache.computeIfAbsent(
pov * 3600 + angle, k -> new BooleanEvent(loop, () -> getPOV(pov) == angle));
pov * 16 + angle.value, k -> new BooleanEvent(loop, () -> getPOV(pov) == angle));
}
}
/**
* Constructs a BooleanEvent instance based around the 0 degree angle (up) of the default (index
* Constructs a BooleanEvent instance based around the up direction of the default (index 0) POV
* on the HID.
*
* @param loop the event loop instance to attach the event to.
* @return a BooleanEvent instance based around the up direction a POV on the HID.
*/
public BooleanEvent povUp(EventLoop loop) {
return pov(POVDirection.Up, loop);
}
/**
* Constructs a BooleanEvent instance based around the up right direction of the default (index 0)
* POV on the HID.
*
* @param loop the event loop instance to attach the event to.
* @return a BooleanEvent instance based around the up right direction of a POV on the HID.
*/
public BooleanEvent povUpRight(EventLoop loop) {
return pov(POVDirection.UpRight, loop);
}
/**
* Constructs a BooleanEvent instance based around the right direction of the default (index 0)
* POV on the HID.
*
* @param loop the event loop instance to attach the event to.
* @return a BooleanEvent instance based around the right direction of a POV on the HID.
*/
public BooleanEvent povRight(EventLoop loop) {
return pov(POVDirection.Right, loop);
}
/**
* Constructs a BooleanEvent instance based around the down right direction of the default (index
* 0) POV on the HID.
*
* @param loop the event loop instance to attach the event to.
* @return a BooleanEvent instance based around the 0 degree angle of a POV on the HID.
*/
public BooleanEvent povUp(EventLoop loop) {
return pov(0, loop);
}
/**
* Constructs a BooleanEvent instance based around the 45 degree angle (right up) of the default
* (index 0) POV on the HID.
*
* @param loop the event loop instance to attach the event to.
* @return a BooleanEvent instance based around the 45 degree angle of a POV on the HID.
*/
public BooleanEvent povUpRight(EventLoop loop) {
return pov(45, loop);
}
/**
* Constructs a BooleanEvent instance based around the 90 degree angle (right) of the default
* (index 0) POV on the HID.
*
* @param loop the event loop instance to attach the event to.
* @return a BooleanEvent instance based around the 90 degree angle of a POV on the HID.
*/
public BooleanEvent povRight(EventLoop loop) {
return pov(90, loop);
}
/**
* Constructs a BooleanEvent instance based around the 135 degree angle (right down) of the
* default (index 0) POV on the HID.
*
* @param loop the event loop instance to attach the event to.
* @return a BooleanEvent instance based around the 135 degree angle of a POV on the HID.
* @return a BooleanEvent instance based around the down right direction of a POV on the HID.
*/
public BooleanEvent povDownRight(EventLoop loop) {
return pov(135, loop);
return pov(POVDirection.DownRight, loop);
}
/**
* Constructs a BooleanEvent instance based around the 180 degree angle (down) of the default
* (index 0) POV on the HID.
* Constructs a BooleanEvent instance based around the down direction of the default (index 0) POV
* on the HID.
*
* @param loop the event loop instance to attach the event to.
* @return a BooleanEvent instance based around the 180 degree angle of a POV on the HID.
* @return a BooleanEvent instance based around the down direction of a POV on the HID.
*/
public BooleanEvent povDown(EventLoop loop) {
return pov(180, loop);
return pov(POVDirection.Down, loop);
}
/**
* Constructs a BooleanEvent instance based around the 225 degree angle (down left) of the default
* (index 0) POV on the HID.
* Constructs a BooleanEvent instance based around the down left direction of the default (index
* 0) POV on the HID.
*
* @param loop the event loop instance to attach the event to.
* @return a BooleanEvent instance based around the 225 degree angle of a POV on the HID.
* @return a BooleanEvent instance based around the down left direction of a POV on the HID.
*/
public BooleanEvent povDownLeft(EventLoop loop) {
return pov(225, loop);
return pov(POVDirection.DownLeft, loop);
}
/**
* Constructs a BooleanEvent instance based around the 270 degree angle (left) of the default
* (index 0) POV on the HID.
* Constructs a BooleanEvent instance based around the left direction of the default (index 0) POV
* on the HID.
*
* @param loop the event loop instance to attach the event to.
* @return a BooleanEvent instance based around the 270 degree angle of a POV on the HID.
* @return a BooleanEvent instance based around the left direction of a POV on the HID.
*/
public BooleanEvent povLeft(EventLoop loop) {
return pov(270, loop);
return pov(POVDirection.Left, loop);
}
/**
* Constructs a BooleanEvent instance based around the 315 degree angle (left up) of the default
* (index 0) POV on the HID.
* Constructs a BooleanEvent instance based around the up left direction of the default (index 0)
* POV on the HID.
*
* @param loop the event loop instance to attach the event to.
* @return a BooleanEvent instance based around the 315 degree angle of a POV on the HID.
* @return a BooleanEvent instance based around the up left direction of a POV on the HID.
*/
public BooleanEvent povUpLeft(EventLoop loop) {
return pov(315, loop);
return pov(POVDirection.UpLeft, loop);
}
/**
@@ -337,7 +326,7 @@ public class GenericHID {
* @return a BooleanEvent instance based around the center of a POV on the HID.
*/
public BooleanEvent povCenter(EventLoop loop) {
return pov(-1, loop);
return pov(POVDirection.Center, loop);
}
/**

View File

@@ -364,10 +364,10 @@ public final class DriverStationSim {
*
* @param stick The joystick number
* @param pov The POV number
* @param value the angle of the POV in degrees, or -1 for not pressed
* @param value the angle of the POV
*/
public static void setJoystickPOV(int stick, int pov, int value) {
DriverStationDataJNI.setJoystickPOV(stick, pov, value);
public static void setJoystickPOV(int stick, int pov, DriverStation.POVDirection value) {
DriverStationDataJNI.setJoystickPOV(stick, pov, value.value);
}
/**

View File

@@ -4,6 +4,7 @@
package edu.wpi.first.wpilibj.simulation;
import edu.wpi.first.wpilibj.DriverStation;
import edu.wpi.first.wpilibj.GenericHID;
/** Class to control a simulated generic joystick. */
@@ -60,7 +61,7 @@ public class GenericHIDSim {
* @param pov the POV to set
* @param value the new value
*/
public void setPOV(int pov, int value) {
public void setPOV(int pov, DriverStation.POVDirection value) {
DriverStationSim.setJoystickPOV(m_port, pov, value);
}
@@ -69,7 +70,7 @@ public class GenericHIDSim {
*
* @param value the new value
*/
public void setPOV(int value) {
public void setPOV(DriverStation.POVDirection value) {
setPOV(0, value);
}