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 edu.wpi.first.wpilibj; 006 007import edu.wpi.first.hal.HAL; 008import edu.wpi.first.wpilibj.event.BooleanEvent; 009import edu.wpi.first.wpilibj.event.EventLoop; 010 011/** 012 * Handle input from Flight Joysticks connected to the Driver Station. 013 * 014 * <p>This class handles standard input that comes from the Driver Station. Each time a value is 015 * requested the most recent value is returned. There is a single class instance for each joystick 016 * and the mapping of ports to hardware buttons depends on the code in the Driver Station. 017 */ 018public class Joystick extends GenericHID { 019 /** Default X axis channel. */ 020 public static final byte kDefaultXChannel = 0; 021 022 /** Default Y axis channel. */ 023 public static final byte kDefaultYChannel = 1; 024 025 /** Default Z axis channel. */ 026 public static final byte kDefaultZChannel = 2; 027 028 /** Default twist axis channel. */ 029 public static final byte kDefaultTwistChannel = 2; 030 031 /** Default throttle axis channel. */ 032 public static final byte kDefaultThrottleChannel = 3; 033 034 /** Represents an analog axis on a joystick. */ 035 public enum AxisType { 036 /** X axis. */ 037 kX(0), 038 /** Y axis. */ 039 kY(1), 040 /** Z axis. */ 041 kZ(2), 042 /** Twist axis. */ 043 kTwist(3), 044 /** Throttle axis. */ 045 kThrottle(4); 046 047 /** AxisType value. */ 048 public final int value; 049 050 AxisType(int value) { 051 this.value = value; 052 } 053 } 054 055 /** Represents a digital button on a joystick. */ 056 public enum ButtonType { 057 /** kTrigger. */ 058 kTrigger(1), 059 /** kTop. */ 060 kTop(2); 061 062 /** ButtonType value. */ 063 public final int value; 064 065 ButtonType(int value) { 066 this.value = value; 067 } 068 } 069 070 private final byte[] m_axes = new byte[AxisType.values().length]; 071 072 /** 073 * Construct an instance of a joystick. 074 * 075 * @param port The port index on the Driver Station that the joystick is plugged into. 076 */ 077 public Joystick(final int port) { 078 super(port); 079 080 m_axes[AxisType.kX.value] = kDefaultXChannel; 081 m_axes[AxisType.kY.value] = kDefaultYChannel; 082 m_axes[AxisType.kZ.value] = kDefaultZChannel; 083 m_axes[AxisType.kTwist.value] = kDefaultTwistChannel; 084 m_axes[AxisType.kThrottle.value] = kDefaultThrottleChannel; 085 086 HAL.reportUsage("HID", port, "Joystick"); 087 } 088 089 /** 090 * Set the channel associated with the X axis. 091 * 092 * @param channel The channel to set the axis to. 093 */ 094 public void setXChannel(int channel) { 095 m_axes[AxisType.kX.value] = (byte) channel; 096 } 097 098 /** 099 * Set the channel associated with the Y axis. 100 * 101 * @param channel The channel to set the axis to. 102 */ 103 public void setYChannel(int channel) { 104 m_axes[AxisType.kY.value] = (byte) channel; 105 } 106 107 /** 108 * Set the channel associated with the Z axis. 109 * 110 * @param channel The channel to set the axis to. 111 */ 112 public void setZChannel(int channel) { 113 m_axes[AxisType.kZ.value] = (byte) channel; 114 } 115 116 /** 117 * Set the channel associated with the throttle axis. 118 * 119 * @param channel The channel to set the axis to. 120 */ 121 public void setThrottleChannel(int channel) { 122 m_axes[AxisType.kThrottle.value] = (byte) channel; 123 } 124 125 /** 126 * Set the channel associated with the twist axis. 127 * 128 * @param channel The channel to set the axis to. 129 */ 130 public void setTwistChannel(int channel) { 131 m_axes[AxisType.kTwist.value] = (byte) channel; 132 } 133 134 /** 135 * Get the channel currently associated with the X axis. 136 * 137 * @return The channel for the axis. 138 */ 139 public int getXChannel() { 140 return m_axes[AxisType.kX.value]; 141 } 142 143 /** 144 * Get the channel currently associated with the Y axis. 145 * 146 * @return The channel for the axis. 147 */ 148 public int getYChannel() { 149 return m_axes[AxisType.kY.value]; 150 } 151 152 /** 153 * Get the channel currently associated with the Z axis. 154 * 155 * @return The channel for the axis. 156 */ 157 public int getZChannel() { 158 return m_axes[AxisType.kZ.value]; 159 } 160 161 /** 162 * Get the channel currently associated with the twist axis. 163 * 164 * @return The channel for the axis. 165 */ 166 public int getTwistChannel() { 167 return m_axes[AxisType.kTwist.value]; 168 } 169 170 /** 171 * Get the channel currently associated with the throttle axis. 172 * 173 * @return The channel for the axis. 174 */ 175 public int getThrottleChannel() { 176 return m_axes[AxisType.kThrottle.value]; 177 } 178 179 /** 180 * Get the X value of the joystick. This depends on the mapping of the joystick connected to the 181 * current port. On most joysticks, positive is to the right. 182 * 183 * @return The X value of the joystick. 184 */ 185 public final double getX() { 186 return getRawAxis(m_axes[AxisType.kX.value]); 187 } 188 189 /** 190 * Get the Y value of the joystick. This depends on the mapping of the joystick connected to the 191 * current port. On most joysticks, positive is to the back. 192 * 193 * @return The Y value of the joystick. 194 */ 195 public final double getY() { 196 return getRawAxis(m_axes[AxisType.kY.value]); 197 } 198 199 /** 200 * Get the z position of the HID. 201 * 202 * @return the z position 203 */ 204 public final double getZ() { 205 return getRawAxis(m_axes[AxisType.kZ.value]); 206 } 207 208 /** 209 * Get the twist value of the current joystick. This depends on the mapping of the joystick 210 * connected to the current port. 211 * 212 * @return The Twist value of the joystick. 213 */ 214 public final double getTwist() { 215 return getRawAxis(m_axes[AxisType.kTwist.value]); 216 } 217 218 /** 219 * Get the throttle value of the current joystick. This depends on the mapping of the joystick 220 * connected to the current port. 221 * 222 * @return The Throttle value of the joystick. 223 */ 224 public final double getThrottle() { 225 return getRawAxis(m_axes[AxisType.kThrottle.value]); 226 } 227 228 /** 229 * Read the state of the trigger on the joystick. 230 * 231 * @return The state of the trigger. 232 */ 233 public boolean getTrigger() { 234 return getRawButton(ButtonType.kTrigger.value); 235 } 236 237 /** 238 * Whether the trigger was pressed since the last check. 239 * 240 * @return Whether the button was pressed since the last check. 241 */ 242 public boolean getTriggerPressed() { 243 return getRawButtonPressed(ButtonType.kTrigger.value); 244 } 245 246 /** 247 * Whether the trigger was released since the last check. 248 * 249 * @return Whether the button was released since the last check. 250 */ 251 public boolean getTriggerReleased() { 252 return getRawButtonReleased(ButtonType.kTrigger.value); 253 } 254 255 /** 256 * Constructs an event instance around the trigger button's digital signal. 257 * 258 * @param loop the event loop instance to attach the event to. 259 * @return an event instance representing the trigger button's digital signal attached to the 260 * given loop. 261 */ 262 public BooleanEvent trigger(EventLoop loop) { 263 return button(ButtonType.kTrigger.value, loop); 264 } 265 266 /** 267 * Read the state of the top button on the joystick. 268 * 269 * @return The state of the top button. 270 */ 271 public boolean getTop() { 272 return getRawButton(ButtonType.kTop.value); 273 } 274 275 /** 276 * Whether the top button was pressed since the last check. 277 * 278 * @return Whether the button was pressed since the last check. 279 */ 280 public boolean getTopPressed() { 281 return getRawButtonPressed(ButtonType.kTop.value); 282 } 283 284 /** 285 * Whether the top button was released since the last check. 286 * 287 * @return Whether the button was released since the last check. 288 */ 289 public boolean getTopReleased() { 290 return getRawButtonReleased(ButtonType.kTop.value); 291 } 292 293 /** 294 * Constructs an event instance around the top button's digital signal. 295 * 296 * @param loop the event loop instance to attach the event to. 297 * @return an event instance representing the top button's digital signal attached to the given 298 * loop. 299 */ 300 public BooleanEvent top(EventLoop loop) { 301 return button(ButtonType.kTop.value, loop); 302 } 303 304 /** 305 * Get the magnitude of the vector formed by the joystick's current position relative to its 306 * origin. 307 * 308 * @return The magnitude of the direction vector 309 */ 310 public double getMagnitude() { 311 return Math.hypot(getX(), getY()); 312 } 313 314 /** 315 * Get the direction of the vector formed by the joystick and its origin in radians. 0 is forward 316 * and clockwise is positive. (Straight right is π/2.) 317 * 318 * @return The direction of the vector in radians 319 */ 320 public double getDirectionRadians() { 321 // https://docs.wpilib.org/en/stable/docs/software/basic-programming/coordinate-system.html#joystick-and-controller-coordinate-system 322 // A positive rotation around the X axis moves the joystick right, and a 323 // positive rotation around the Y axis moves the joystick backward. When 324 // treating them as translations, 0 radians is measured from the right 325 // direction, and angle increases clockwise. 326 // 327 // It's rotated 90 degrees CCW (y is negated and the arguments are reversed) 328 // so that 0 radians is forward. 329 return Math.atan2(getX(), -getY()); 330 } 331 332 /** 333 * Get the direction of the vector formed by the joystick and its origin in degrees. 0 is forward 334 * and clockwise is positive. (Straight right is 90.) 335 * 336 * @return The direction of the vector in degrees 337 */ 338 public double getDirectionDegrees() { 339 return Math.toDegrees(getDirectionRadians()); 340 } 341}