001    /*----------------------------------------------------------------------------*/
002    /* Copyright (c) FIRST 2008-2012. 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    package edu.wpi.first.wpilibj;
008    
009    import com.sun.squawk.util.MathUtils;
010    import edu.wpi.first.wpilibj.communication.UsageReporting;
011    import edu.wpi.first.wpilibj.parsing.IInputOutput;
012    
013    /**
014     * Handle input from standard Joysticks connected to the Driver Station.
015     * This class handles standard input that comes from the Driver Station. Each time a value is requested
016     * the most recent value is returned. There is a single class instance for each joystick and the mapping
017     * of ports to hardware buttons depends on the code in the driver station.
018     */
019    public class Joystick extends GenericHID implements IInputOutput{
020    
021        static final byte kDefaultXAxis = 1;
022        static final byte kDefaultYAxis = 2;
023        static final byte kDefaultZAxis = 3;
024        static final byte kDefaultTwistAxis = 3;
025        static final byte kDefaultThrottleAxis = 4;
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 static class AxisType {
033    
034            /**
035             * The integer value representing this enumeration
036             */
037            public final int value;
038            static final int kX_val = 0;
039            static final int kY_val = 1;
040            static final int kZ_val = 2;
041            static final int kTwist_val = 3;
042            static final int kThrottle_val = 4;
043            static final int kNumAxis_val = 5;
044            /**
045             * axis: x-axis
046             */
047            public static final AxisType kX = new AxisType(kX_val);
048            /**
049             * axis: y-axis
050             */
051            public static final AxisType kY = new AxisType(kY_val);
052            /**
053             * axis: z-axis
054             */
055            public static final AxisType kZ = new AxisType(kZ_val);
056            /**
057             * axis: twist
058             */
059            public static final AxisType kTwist = new AxisType(kTwist_val);
060            /**
061             * axis: throttle
062             */
063            public static final AxisType kThrottle = new AxisType(kThrottle_val);
064            /**
065             * axis: number of axis
066             */
067            public static final AxisType kNumAxis = new AxisType(kNumAxis_val);
068    
069            private AxisType(int value) {
070                this.value = value;
071            }
072        }
073    
074        /**
075         * Represents a digital button on the JoyStick
076         */
077        public static class ButtonType {
078    
079            /**
080             * The integer value representing this enumeration
081             */
082            public final int value;
083            static final int kTrigger_val = 0;
084            static final int kTop_val = 1;
085            static final int kNumButton_val = 2;
086            /**
087             * button: trigger
088             */
089            public static final ButtonType kTrigger = new ButtonType((kTrigger_val));
090            /**
091             * button: top button
092             */
093            public static final ButtonType kTop = new ButtonType(kTop_val);
094            /**
095             * button: num button types
096             */
097            public static final ButtonType kNumButton = new ButtonType((kNumButton_val));
098    
099            private ButtonType(int value) {
100                this.value = value;
101            }
102        }
103        private DriverStation m_ds;
104        private final int m_port;
105        private final byte[] m_axes;
106        private final byte[] m_buttons;
107    
108        /**
109         * Construct an instance of a joystick.
110         * The joystick index is the usb port on the drivers station.
111         *
112         * @param port The port on the driver station that the joystick is plugged into.
113         */
114        public Joystick(final int port) {
115            this(port, AxisType.kNumAxis.value, ButtonType.kNumButton.value);
116    
117            m_axes[AxisType.kX.value] = kDefaultXAxis;
118            m_axes[AxisType.kY.value] = kDefaultYAxis;
119            m_axes[AxisType.kZ.value] = kDefaultZAxis;
120            m_axes[AxisType.kTwist.value] = kDefaultTwistAxis;
121            m_axes[AxisType.kThrottle.value] = kDefaultThrottleAxis;
122    
123            m_buttons[ButtonType.kTrigger.value] = kDefaultTriggerButton;
124            m_buttons[ButtonType.kTop.value] = kDefaultTopButton;
125    
126            UsageReporting.report(UsageReporting.kResourceType_Joystick, port);
127        }
128    
129        /**
130         * Protected version of the constructor to be called by sub-classes.
131         *
132         * This constructor allows the subclass to configure the number of constants
133         * for axes and buttons.
134         *
135         * @param port The port on the driver station that the joystick is plugged into.
136         * @param numAxisTypes The number of axis types in the enum.
137         * @param numButtonTypes The number of button types in the enum.
138         */
139        protected Joystick(int port, int numAxisTypes, int numButtonTypes) {
140            m_ds = DriverStation.getInstance();
141            m_axes = new byte[numAxisTypes];
142            m_buttons = new byte[numButtonTypes];
143            m_port = port;
144        }
145    
146        /**
147         * Get the X value of the joystick.
148         * This depends on the mapping of the joystick connected to the current port.
149         *
150         * @param hand Unused
151         * @return The X value of the joystick.
152         */
153        public double getX(Hand hand) {
154            return getRawAxis(m_axes[AxisType.kX.value]);
155        }
156    
157        /**
158         * Get the Y value of the joystick.
159         * This depends on the mapping of the joystick connected to the current port.
160         *
161         * @param hand Unused
162         * @return The Y value of the joystick.
163         */
164        public double getY(Hand hand) {
165            return getRawAxis(m_axes[AxisType.kY.value]);
166        }
167    
168        /**
169         * Get the Z value of the joystick.
170         * This depends on the mapping of the joystick connected to the current port.
171         *
172         * @param hand Unused
173         * @return The Z value of the joystick.
174         */
175        public double getZ(Hand hand) {
176            return getRawAxis(m_axes[AxisType.kZ.value]);
177        }
178    
179        /**
180         * Get the twist value of the current joystick.
181         * This depends on the mapping of the joystick connected to the current port.
182         *
183         * @return The Twist value of the joystick.
184         */
185        public double getTwist() {
186            return getRawAxis(m_axes[AxisType.kTwist.value]);
187        }
188    
189        /**
190         * Get the throttle value of the current joystick.
191         * This depends on the mapping of the joystick connected to the current port.
192         *
193         * @return The Throttle value of the joystick.
194         */
195        public double getThrottle() {
196            return getRawAxis(m_axes[AxisType.kThrottle.value]);
197        }
198    
199        /**
200         * Get the value of the axis.
201         *
202         * @param axis The axis to read [1-6].
203         * @return The value of the axis.
204         */
205        public double getRawAxis(final int axis) {
206            return m_ds.getStickAxis(m_port, axis);
207        }
208    
209        /**
210         * For the current joystick, return the axis determined by the argument.
211         *
212         * This is for cases where the joystick axis is returned programatically, otherwise one of the
213         * previous functions would be preferable (for example getX()).
214         *
215         * @param axis The axis to read.
216         * @return The value of the axis.
217         */
218        public double getAxis(final AxisType axis) {
219            switch (axis.value) {
220                case AxisType.kX_val:
221                    return getX();
222                case AxisType.kY_val:
223                    return getY();
224                case AxisType.kZ_val:
225                    return getZ();
226                case AxisType.kTwist_val:
227                    return getTwist();
228                case AxisType.kThrottle_val:
229                    return getThrottle();
230                default:
231                    return 0.0;
232            }
233        }
234    
235        /**
236         * Read the state of the trigger on the joystick.
237         *
238         * Look up which button has been assigned to the trigger and read its state.
239         *
240         * @param hand This parameter is ignored for the Joystick class and is only here to complete the GenericHID interface.
241         * @return The state of the trigger.
242         */
243        public boolean getTrigger(Hand hand) {
244            return getRawButton(m_buttons[ButtonType.kTrigger.value]);
245        }
246    
247        /**
248         * Read the state of the top button on the joystick.
249         *
250         * Look up which button has been assigned to the top and read its state.
251         *
252         * @param hand This parameter is ignored for the Joystick class and is only here to complete the GenericHID interface.
253         * @return The state of the top button.
254         */
255        public boolean getTop(Hand hand) {
256            return getRawButton(m_buttons[ButtonType.kTop.value]);
257        }
258    
259        /**
260         * This is not supported for the Joystick.
261         * This method is only here to complete the GenericHID interface.
262         *
263         * @param hand This parameter is ignored for the Joystick class and is only here to complete the GenericHID interface.
264         * @return The state of the bumper (always false)
265         */
266        public boolean getBumper(Hand hand) {
267            return false;
268        }
269    
270        /**
271         * Get the button value for buttons 1 through 12.
272         *
273         * The buttons are returned in a single 16 bit value with one bit representing the state
274         * of each button. The appropriate button is returned as a boolean value.
275         *
276         * @param button The button number to be read.
277         * @return The state of the button.
278         */
279        public boolean getRawButton(final int button) {
280            return ((0x1 << (button - 1)) & m_ds.getStickButtons(m_port)) != 0;
281        }
282    
283        /**
284         * Get buttons based on an enumerated type.
285         *
286         * The button type will be looked up in the list of buttons and then read.
287         *
288         * @param button The type of button to read.
289         * @return The state of the button.
290         */
291        public boolean getButton(ButtonType button) {
292            switch (button.value) {
293                case ButtonType.kTrigger_val:
294                    return getTrigger();
295                case ButtonType.kTop_val:
296                    return getTop();
297                default:
298                    return false;
299            }
300        }
301    
302        /**
303         * Get the magnitude of the direction vector formed by the joystick's
304         * current position relative to its origin
305         *
306         * @return The magnitude of the direction vector
307         */
308        public double getMagnitude() {
309            return Math.sqrt(MathUtils.pow(getX(), 2) + MathUtils.pow(getY(), 2));
310        }
311    
312        /**
313         * Get the direction of the vector formed by the joystick and its origin
314         * in radians
315         *
316         * @return The direction of the vector in radians
317         */
318        public double getDirectionRadians() {
319            return MathUtils.atan2(getX(), -getY());
320        }
321    
322        /**
323         * Get the direction of the vector formed by the joystick and its origin
324         * in degrees
325         *
326         * uses acos(-1) to represent Pi due to absence of readily accessable Pi
327         * constant in C++
328         *
329         * @return The direction of the vector in degrees
330         */
331        public double getDirectionDegrees() {
332            return Math.toDegrees(getDirectionRadians());
333        }
334    
335        /**
336         * Get the channel currently associated with the specified axis.
337         *
338         * @param axis The axis to look up the channel for.
339         * @return The channel fr the axis.
340         */
341        public int getAxisChannel(AxisType axis) {
342            return m_axes[axis.value];
343        }
344    
345        /**
346         * Set the channel associated with a specified axis.
347         *
348         * @param axis The axis to set the channel for.
349         * @param channel The channel to set the axis to.
350         */
351        public void setAxisChannel(AxisType axis, int channel) {
352            m_axes[axis.value] = (byte) channel;
353        }
354    }