001// Copyright (c) FIRST and other WPILib contributors. 002// Open Source Software; you can modify and/or share it under the terms of 003// the WPILib BSD license file in the root directory of this project. 004 005package org.wpilib.driverstation; 006 007import java.util.Optional; 008import org.wpilib.math.geometry.Rotation2d; 009import org.wpilib.system.Timer; 010 011/** A controller POV direction. */ 012public enum POVDirection { 013 /** POV center. */ 014 CENTER(0x00), 015 /** POV up. */ 016 UP(0x01), 017 /** POV up right. */ 018 UP_RIGHT(0x01 | 0x02), 019 /** POV right. */ 020 RIGHT(0x02), 021 /** POV down right. */ 022 DOWN_RIGHT(0x02 | 0x04), 023 /** POV down. */ 024 DOWN(0x04), 025 /** POV down left. */ 026 DOWN_LEFT(0x04 | 0x08), 027 /** POV left. */ 028 LEFT(0x08), 029 /** POV up left. */ 030 UP_LEFT(0x01 | 0x08); 031 032 private static final double INVALID_POV_VALUE_INTERVAL = 1.0; 033 private static double s_nextMessageTime; 034 035 /** 036 * Converts a byte value into a POVDirection enum value. 037 * 038 * @param value The byte value to convert. 039 * @return The corresponding POVDirection enum value. 040 * @throws IllegalArgumentException If value does not correspond to a POVDirection. 041 */ 042 public static POVDirection of(byte value) { 043 for (var direction : values()) { 044 if (direction.value == value) { 045 return direction; 046 } 047 } 048 double currentTime = Timer.getTimestamp(); 049 if (currentTime > s_nextMessageTime) { 050 DriverStationErrors.reportError("Invalid POV value " + value + "!", false); 051 s_nextMessageTime = currentTime + INVALID_POV_VALUE_INTERVAL; 052 } 053 return CENTER; 054 } 055 056 /** The corresponding HAL value. */ 057 public final byte value; 058 059 POVDirection(int value) { 060 this.value = (byte) value; 061 } 062 063 /** 064 * Gets the angle of a POVDirection. 065 * 066 * @return The angle clockwise from straight up, or Optional.empty() if this POVDirection is 067 * CENTER. 068 */ 069 public Optional<Rotation2d> getAngle() { 070 return switch (this) { 071 case CENTER -> Optional.empty(); 072 case UP -> Optional.of(Rotation2d.fromDegrees(0)); 073 case UP_RIGHT -> Optional.of(Rotation2d.fromDegrees(45)); 074 case RIGHT -> Optional.of(Rotation2d.fromDegrees(90)); 075 case DOWN_RIGHT -> Optional.of(Rotation2d.fromDegrees(135)); 076 case DOWN -> Optional.of(Rotation2d.fromDegrees(180)); 077 case DOWN_LEFT -> Optional.of(Rotation2d.fromDegrees(225)); 078 case LEFT -> Optional.of(Rotation2d.fromDegrees(270)); 079 case UP_LEFT -> Optional.of(Rotation2d.fromDegrees(315)); 080 }; 081 } 082}