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