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.cldc.jna.Pointer;
010    import com.sun.cldc.jna.Structure;
011    import edu.wpi.first.wpilibj.communication.FRCControl;
012    import edu.wpi.first.wpilibj.communication.UsageReporting;
013    
014    /**
015     * @author bradmiller
016     * Handles input from the Joystick data sent by the FRC Kinect Server
017     * when used with a Kinect device connected to the Driver Station.
018     * Each time a value is requested the most recent value is returned.
019     * Default gestures embedded in the FRC Kinect Server are described
020     * in the document Getting Started with Microsoft Kinect for FRC.
021     */
022    public class KinectStick extends GenericHID {
023    
024        private final static byte kJoystickDataID = 24;
025        private final static byte kJoystickDataSize = 18;
026        private int m_recentPacketNumber;
027    
028        private int m_id;
029    
030        static class JoystickDataBlock extends Structure {
031    
032            byte joystick1[] = new byte[6];
033            short button1;
034            byte joystick2[] = new byte[6];
035            short button2;
036    
037            public static final int size = kJoystickDataSize - 2;
038    
039            JoystickDataBlock(Pointer backingMemory) {
040                useMemory(backingMemory);
041            }
042    
043            public void read() {
044                backingNativeMemory.getBytes(0, joystick1, 0, 6);
045                button1 = backingNativeMemory.getShort(6);
046                backingNativeMemory.getBytes(8, joystick2, 0, 6);
047                button2 = backingNativeMemory.getShort(14);
048            }
049    
050            public void write() {
051                backingNativeMemory.setBytes(0, joystick1, 0, 6);
052                backingNativeMemory.setShort(6, button1);
053                backingNativeMemory.setBytes(8, joystick2, 0, 6);
054                backingNativeMemory.setShort(14, button2);
055            }
056    
057            public int size() {
058                return size;
059            }
060        }
061    
062        class JoystickData extends FRCControl.DynamicControlData {
063    
064            JoystickDataBlock data;
065    
066            {
067                allocateMemory();
068                data = new JoystickDataBlock(
069                        new Pointer(backingNativeMemory.address().toUWord().toPrimitive() + 2,
070                                    JoystickDataBlock.size));
071            }
072    
073            public void read() {
074                data.read();
075            }
076    
077            public void write() {
078                data.write();
079            }
080    
081            public int size() {
082                return kJoystickDataSize;
083            }
084    
085            public void copy(JoystickData dest) {
086                write();
087                Pointer.copyBytes(backingNativeMemory, 0, dest.backingNativeMemory, 0, size());
088                dest.read();
089            }
090        }
091        JoystickData tempOutputData = new JoystickData();
092    
093        /**
094         * Construct an instance of a KinectStick.
095         * @param id which KinectStick to read, in the default gestures
096         * an id of 1 corresponds to the left arm and 2 to the right arm.
097         */
098        public KinectStick(int id) {
099            m_id = id;
100    
101            UsageReporting.report(UsageReporting.kResourceType_KinectStick, id);
102        }
103    
104        /**
105         * Update the data in this class with the latest data from the
106         * Driver Station.
107         */
108        private void getData() {
109            if (m_recentPacketNumber !=  DriverStation.getInstance().getPacketNumber()){
110                m_recentPacketNumber = DriverStation.getInstance().getPacketNumber();
111                int retVal = FRCControl.getDynamicControlData(kJoystickDataID, tempOutputData, tempOutputData.size(), 5);
112                if (retVal != 0) {
113                    System.err.println("Bad retval: " + retVal);
114                }
115            }
116        }
117    
118        /**
119         * Convert a value from a byte to a double in the
120         * -1 to 1 range
121         * @param rawValue the value to convert
122         * @return the normalized value
123         */
124        private double normalize(byte rawValue) {
125            if(rawValue >= 0)
126                return rawValue / 127.0;
127            else
128                return rawValue / 128.0;
129        }
130    
131        /**
132         * Get the X value of the KinectStick. This axis
133         * is unimplemented in the default gestures but can
134         * be populated by teams editing the Kinect Server.
135         * See (@link Joystick for axis number mapping)
136         * @param hand Unused
137         * @return The X value of the KinectStick
138         */
139        public double getX(Hand hand) {
140            getData();
141            return getRawAxis(Joystick.kDefaultXAxis);
142        }
143    
144        /**
145         * Get the Y value of the KinectStick. This axis
146         * represents arm angle in the default gestures
147         * See (@link Joystick for axis number mapping)
148         * @param hand Unused
149         * @return The Y value of the KinectStick
150         */
151        public double getY(Hand hand) {
152            getData();
153            return getRawAxis(Joystick.kDefaultYAxis);
154        }
155    
156        /**
157         * Get the Z value of the KinectStick. This axis
158         * is unimplemented in the default gestures but can
159         * be populated by teams editing the Kinect Server.
160         * See (@link Joystick for axis number mapping)
161         * @param hand Unused
162         * @return The Z value of the KinectStick
163         */
164        public double getZ(Hand hand) {
165            getData();
166            return getRawAxis(Joystick.kDefaultZAxis);
167        }
168    
169        /**
170         * Get the Twist value of the KinectStick. This axis
171         * is unimplemented in the default gestures but can
172         * be populated by teams editing the Kinect Server.
173         * See (@link Joystick for axis number mapping)
174         * @return The Twist value of the KinectStick
175         */
176        public double getTwist() {
177            getData();
178            return getRawAxis(Joystick.kDefaultTwistAxis);
179        }
180    
181        /**
182         * Get the Throttle value of the KinectStick. This axis
183         * is unimplemented in the default gestures but can
184         * be populated by teams editing the Kinect Server.
185         * See (@link Joystick for axis number mapping)
186         * @return The Throttle value of the KinectStick
187         */
188        public double getThrottle() {
189            getData();
190            return getRawAxis(Joystick.kDefaultThrottleAxis);
191        }
192    
193        /**
194         * Get the value of the KinectStick axis.
195         *
196         * @param axis The axis to read [1-6].
197         * @return The value of the axis
198         */
199        public double getRawAxis(int axis) {
200            if (axis < 1 || axis > DriverStation.kJoystickAxes)
201                return 0.0;
202    
203            getData();
204            if (m_id == 1) {
205                return normalize(tempOutputData.data.joystick1[axis-1]);
206            } else {
207                return normalize(tempOutputData.data.joystick2[axis-1]);
208            }
209        }
210    
211        /**
212         * Get the button value for the button set as the default trigger in
213         * (@link Joystick)
214         *
215         * @param hand Unused
216         * @return The state of the button.
217         */
218        public boolean getTrigger(Hand hand) {
219                    getData();
220            return (tempOutputData.data.button1 & (short) Joystick.kDefaultTriggerButton) != 0;
221        }
222    
223        /**
224         * Get the button value for the button set as the default top in
225         * (@link Joystick)
226         *
227         * @param hand Unused
228         * @return The state of the button.
229         */
230        public boolean getTop(Hand hand) {
231                    getData();
232            return (tempOutputData.data.button1 & (short) Joystick.kDefaultTopButton) != 0;
233        }
234    
235        /**
236         * Get the button value for the button set as the default bumper in
237         * (@link Joystick)
238         *
239         * @param hand Unused
240         * @return The state of the button.
241         */
242        public boolean getBumper(Hand hand) {
243                    getData();
244            return (tempOutputData.data.button1 & (short) 4) != 0;
245        }
246    
247        /**
248         * Get the button value for buttons 1 through 12. The default gestures
249         * implement only 9 buttons.
250         *
251         * The appropriate button is returned as a boolean value.
252         *
253         * @param button The button number to be read.
254         * @return The state of the button.
255         */
256        public boolean getRawButton(int button) {
257                    getData();
258            return (tempOutputData.data.button1 & (short) (1 << (button - 1))) != 0;
259        }
260    }