001/*----------------------------------------------------------------------------*/ 002/* Copyright (c) FIRST 2008-2017. All Rights Reserved. */ 003/* Open Source Software - may be modified and shared by FRC teams. The code */ 004/* must be accompanied by the FIRST BSD license file in the root directory of */ 005/* the project. */ 006/*----------------------------------------------------------------------------*/ 007 008package edu.wpi.first.wpilibj; 009 010import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType; 011import edu.wpi.first.wpilibj.hal.HAL; 012 013/** 014 * Handle input from standard Joysticks connected to the Driver Station. This class handles standard 015 * input that comes from the Driver Station. Each time a value is requested the most recent value is 016 * returned. There is a single class instance for each joystick and the mapping of ports to hardware 017 * buttons depends on the code in the Driver Station. 018 */ 019public class Joystick extends JoystickBase { 020 021 static final byte kDefaultXAxis = 0; 022 static final byte kDefaultYAxis = 1; 023 static final byte kDefaultZAxis = 2; 024 static final byte kDefaultTwistAxis = 2; 025 static final byte kDefaultThrottleAxis = 3; 026 static final int kDefaultTriggerButton = 1; 027 static final int kDefaultTopButton = 2; 028 029 /** 030 * Represents an analog axis on a joystick. 031 */ 032 public enum AxisType { 033 kX(0), kY(1), kZ(2), kTwist(3), kThrottle(4), kNumAxis(5); 034 035 @SuppressWarnings("MemberName") 036 public final int value; 037 038 private AxisType(int value) { 039 this.value = value; 040 } 041 } 042 043 /** 044 * Represents a digital button on the JoyStick. 045 */ 046 public enum ButtonType { 047 kTrigger(0), kTop(1), kNumButton(2); 048 049 @SuppressWarnings("MemberName") 050 public final int value; 051 052 private ButtonType(int value) { 053 this.value = value; 054 } 055 } 056 057 private final DriverStation m_ds; 058 private final byte[] m_axes; 059 private final byte[] m_buttons; 060 private int m_outputs; 061 private short m_leftRumble; 062 private short m_rightRumble; 063 064 /** 065 * Construct an instance of a joystick. The joystick index is the USB port on the drivers 066 * station. 067 * 068 * @param port The port on the Driver Station that the joystick is plugged into. 069 */ 070 public Joystick(final int port) { 071 this(port, AxisType.kNumAxis.value, ButtonType.kNumButton.value); 072 073 m_axes[AxisType.kX.value] = kDefaultXAxis; 074 m_axes[AxisType.kY.value] = kDefaultYAxis; 075 m_axes[AxisType.kZ.value] = kDefaultZAxis; 076 m_axes[AxisType.kTwist.value] = kDefaultTwistAxis; 077 m_axes[AxisType.kThrottle.value] = kDefaultThrottleAxis; 078 079 m_buttons[ButtonType.kTrigger.value] = kDefaultTriggerButton; 080 m_buttons[ButtonType.kTop.value] = kDefaultTopButton; 081 082 HAL.report(tResourceType.kResourceType_Joystick, port); 083 } 084 085 /** 086 * Protected version of the constructor to be called by sub-classes. 087 * 088 * <p>This constructor allows the subclass to configure the number of constants for axes and 089 * buttons. 090 * 091 * @param port The port on the Driver Station that the joystick is plugged into. 092 * @param numAxisTypes The number of axis types in the enum. 093 * @param numButtonTypes The number of button types in the enum. 094 */ 095 protected Joystick(int port, int numAxisTypes, int numButtonTypes) { 096 super(port); 097 098 m_ds = DriverStation.getInstance(); 099 m_axes = new byte[numAxisTypes]; 100 m_buttons = new byte[numButtonTypes]; 101 } 102 103 /** 104 * Get the X value of the joystick. This depends on the mapping of the joystick connected to the 105 * current port. 106 * 107 * @param hand Unused 108 * @return The X value of the joystick. 109 */ 110 @Override 111 public final double getX(Hand hand) { 112 return getRawAxis(m_axes[AxisType.kX.value]); 113 } 114 115 /** 116 * Get the Y value of the joystick. This depends on the mapping of the joystick connected to the 117 * current port. 118 * 119 * @param hand Unused 120 * @return The Y value of the joystick. 121 */ 122 @Override 123 public final double getY(Hand hand) { 124 return getRawAxis(m_axes[AxisType.kY.value]); 125 } 126 127 @Override 128 public final double getZ(Hand hand) { 129 return getRawAxis(m_axes[AxisType.kZ.value]); 130 } 131 132 /** 133 * Get the twist value of the current joystick. This depends on the mapping of the joystick 134 * connected to the current port. 135 * 136 * @return The Twist value of the joystick. 137 */ 138 public double getTwist() { 139 return getRawAxis(m_axes[AxisType.kTwist.value]); 140 } 141 142 /** 143 * Get the throttle value of the current joystick. This depends on the mapping of the joystick 144 * connected to the current port. 145 * 146 * @return The Throttle value of the joystick. 147 */ 148 public double getThrottle() { 149 return getRawAxis(m_axes[AxisType.kThrottle.value]); 150 } 151 152 /** 153 * Get the value of the axis. 154 * 155 * @param axis The axis to read, starting at 0. 156 * @return The value of the axis. 157 */ 158 public double getRawAxis(final int axis) { 159 return m_ds.getStickAxis(getPort(), axis); 160 } 161 162 /** 163 * For the current joystick, return the axis determined by the argument. 164 * 165 * <p>This is for cases where the joystick axis is returned programatically, otherwise one of the 166 * previous functions would be preferable (for example getX()). 167 * 168 * @param axis The axis to read. 169 * @return The value of the axis. 170 */ 171 public double getAxis(final AxisType axis) { 172 switch (axis) { 173 case kX: 174 return getX(); 175 case kY: 176 return getY(); 177 case kZ: 178 return getZ(); 179 case kTwist: 180 return getTwist(); 181 case kThrottle: 182 return getThrottle(); 183 default: 184 return 0.0; 185 } 186 } 187 188 /** 189 * For the current joystick, return the number of axis. 190 */ 191 public int getAxisCount() { 192 return m_ds.getStickAxisCount(getPort()); 193 } 194 195 /** 196 * Read the state of the trigger on the joystick. 197 * 198 * <p>Look up which button has been assigned to the trigger and read its state. 199 * 200 * @param hand This parameter is ignored for the Joystick class and is only here to complete the 201 * GenericHID interface. 202 * @return The state of the trigger. 203 */ 204 @SuppressWarnings("PMD.UnusedFormalParameter") 205 public boolean getTrigger(Hand hand) { 206 return getRawButton(m_buttons[ButtonType.kTrigger.value]); 207 } 208 209 /** 210 * Read the state of the top button on the joystick. 211 * 212 * <p>Look up which button has been assigned to the top and read its state. 213 * 214 * @param hand This parameter is ignored for the Joystick class and is only here to complete the 215 * GenericHID interface. 216 * @return The state of the top button. 217 */ 218 @SuppressWarnings("PMD.UnusedFormalParameter") 219 public boolean getTop(Hand hand) { 220 return getRawButton(m_buttons[ButtonType.kTop.value]); 221 } 222 223 @Override 224 public int getPOV(int pov) { 225 return m_ds.getStickPOV(getPort(), pov); 226 } 227 228 @Override 229 public int getPOVCount() { 230 return m_ds.getStickPOVCount(getPort()); 231 } 232 233 /** 234 * This is not supported for the Joystick. This method is only here to complete the GenericHID 235 * interface. 236 * 237 * @param hand This parameter is ignored for the Joystick class and is only here to complete the 238 * GenericHID interface. 239 * @return The state of the bumper (always false) 240 */ 241 @SuppressWarnings("PMD.UnusedFormalParameter") 242 public boolean getBumper(Hand hand) { 243 return false; 244 } 245 246 /** 247 * Get the button value (starting at button 1). 248 * 249 * <p>The appropriate button is returned as a boolean value. 250 * 251 * @param button The button number to be read (starting at 1). 252 * @return The state of the button. 253 */ 254 public boolean getRawButton(final int button) { 255 return m_ds.getStickButton(getPort(), (byte) button); 256 } 257 258 /** 259 * For the current joystick, return the number of buttons. 260 */ 261 public int getButtonCount() { 262 return m_ds.getStickButtonCount(getPort()); 263 } 264 265 /** 266 * Get buttons based on an enumerated type. 267 * 268 * <p>The button type will be looked up in the list of buttons and then read. 269 * 270 * @param button The type of button to read. 271 * @return The state of the button. 272 */ 273 public boolean getButton(ButtonType button) { 274 switch (button) { 275 case kTrigger: 276 return getTrigger(); 277 case kTop: 278 return getTop(); 279 default: 280 return false; 281 } 282 } 283 284 /** 285 * Get the magnitude of the direction vector formed by the joystick's current position relative to 286 * its origin. 287 * 288 * @return The magnitude of the direction vector 289 */ 290 public double getMagnitude() { 291 return Math.sqrt(Math.pow(getX(), 2) + Math.pow(getY(), 2)); 292 } 293 294 /** 295 * Get the direction of the vector formed by the joystick and its origin in radians. 296 * 297 * @return The direction of the vector in radians 298 */ 299 public double getDirectionRadians() { 300 return Math.atan2(getX(), -getY()); 301 } 302 303 /** 304 * Get the direction of the vector formed by the joystick and its origin in degrees. 305 * 306 * <p>Uses acos(-1) to represent Pi due to absence of readily accessable Pi constant in C++ 307 * 308 * @return The direction of the vector in degrees 309 */ 310 public double getDirectionDegrees() { 311 return Math.toDegrees(getDirectionRadians()); 312 } 313 314 /** 315 * Get the channel currently associated with the specified axis. 316 * 317 * @param axis The axis to look up the channel for. 318 * @return The channel fr the axis. 319 */ 320 public int getAxisChannel(AxisType axis) { 321 return m_axes[axis.value]; 322 } 323 324 /** 325 * Set the channel associated with a specified axis. 326 * 327 * @param axis The axis to set the channel for. 328 * @param channel The channel to set the axis to. 329 */ 330 public void setAxisChannel(AxisType axis, int channel) { 331 m_axes[axis.value] = (byte) channel; 332 } 333 334 /** 335 * Get the value of isXbox for the current joystick. 336 * 337 * @return A boolean that is true if the controller is an xbox controller. 338 */ 339 public boolean getIsXbox() { 340 return m_ds.getJoystickIsXbox(getPort()); 341 } 342 343 /** 344 * Get the axis type of a joystick axis. 345 * 346 * @return the axis type of a joystick axis. 347 */ 348 public int getAxisType(int axis) { 349 return m_ds.getJoystickAxisType(getPort(), axis); 350 } 351 352 /** 353 * Get the type of the HID. 354 * 355 * @return the type of the HID. 356 */ 357 @Override 358 public HIDType getType() { 359 return HIDType.values()[m_ds.getJoystickType(getPort())]; 360 } 361 362 /** 363 * Get the name of the HID. 364 * 365 * @return the name of the HID. 366 */ 367 @Override 368 public String getName() { 369 return m_ds.getJoystickName(getPort()); 370 } 371 372 @Override 373 public void setOutput(int outputNumber, boolean value) { 374 m_outputs = (m_outputs & ~(1 << (outputNumber - 1))) | ((value ? 1 : 0) << (outputNumber - 1)); 375 HAL.setJoystickOutputs((byte) getPort(), m_outputs, m_leftRumble, m_rightRumble); 376 } 377 378 @Override 379 public void setOutputs(int value) { 380 m_outputs = value; 381 HAL.setJoystickOutputs((byte) getPort(), m_outputs, m_leftRumble, m_rightRumble); 382 } 383 384 @Override 385 public void setRumble(RumbleType type, double value) { 386 if (value < 0) { 387 value = 0; 388 } else if (value > 1) { 389 value = 1; 390 } 391 if (type == RumbleType.kLeftRumble) { 392 m_leftRumble = (short) (value * 65535); 393 } else { 394 m_rightRumble = (short) (value * 65535); 395 } 396 HAL.setJoystickOutputs((byte) getPort(), m_outputs, m_leftRumble, m_rightRumble); 397 } 398}