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