blob: 3f1c9310b80b2f85a263e9439f9ef341d7425f9c [file] [log] [blame]
jerrymf1579332013-02-07 01:56:28 +00001/*----------------------------------------------------------------------------*/
2/* Copyright (c) FIRST 2011. All Rights Reserved. */
3/* Open Source Software - may be modified and shared by FRC teams. The code */
4/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */
5/*----------------------------------------------------------------------------*/
6
7#include "Kinect.h"
8
9#include "DriverStation.h"
10#include "NetworkCommunication/FRCComm.h"
11#include "NetworkCommunication/UsageReporting.h"
12#include "Skeleton.h"
13#include "Synchronized.h"
14#include "WPIErrors.h"
15
16#define kHeaderBundleID kFRC_NetworkCommunication_DynamicType_Kinect_Header
17#define kSkeletonExtraBundleID kFRC_NetworkCommunication_DynamicType_Kinect_Extra1
18#define kSkeletonBundleID kFRC_NetworkCommunication_DynamicType_Kinect_Vertices1
19
20Kinect *Kinect::_instance = NULL;
21
22Kinect::Kinect() :
23 m_recentPacketNumber(0),
24 m_numberOfPlayers(0)
25{
26 AddToSingletonList();
27 m_dataLock = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE | SEM_DELETE_SAFE);
28
29 nUsageReporting::report(nUsageReporting::kResourceType_Kinect, 0);
30}
31
32Kinect::~Kinect()
33{
34 semTake(m_dataLock, WAIT_FOREVER);
35 semDelete(m_dataLock);
36}
37
38/**
39 * Get the one and only Kinect object
40 * @returns pointer to a Kinect
41 */
42Kinect *Kinect::GetInstance()
43{
44 if (_instance == NULL)
45 _instance = new Kinect();
46 return _instance;
47}
48
49/**
50 * Get the number of tracked players on the Kinect
51 * @return the number of players being actively tracked
52 */
53int Kinect::GetNumberOfPlayers()
54{
55 UpdateData();
56 return m_numberOfPlayers;
57}
58
59/**
60 * Get the floor clip plane as defined in the Kinect SDK
61 * @return The floor clip plane
62 */
63Kinect::Point4 Kinect::GetFloorClipPlane()
64{
65 UpdateData();
66 return m_floorClipPlane;
67}
68
69/**
70 * Get the gravity normal from the kinect as defined in the Kinect SDK
71 * @return The gravity normal (w is ignored)
72 */
73Kinect::Point4 Kinect::GetGravityNormal()
74{
75 UpdateData();
76 return m_gravityNormal;
77}
78
79/**
80 * Get the skeleton data
81 * Returns the detected skeleton data from the kinect as defined in the Kinect SDK
82 * @param skeletonIndex Which of (potentially 2) skeletons to return. This is ignored in this implementation and
83 * only a single skeleton is supported for the FRC release default gesture interpretation.
84 * @return The current version of the skeleton object.
85 */
86Skeleton Kinect::GetSkeleton(int skeletonIndex)
87{
88 if (skeletonIndex <= 0 || skeletonIndex > kNumSkeletons)
89 {
90 wpi_setWPIErrorWithContext(ParameterOutOfRange, "Skeleton index must be 1");
91 return Skeleton();
92 }
93 UpdateData();
94 return m_skeletons[skeletonIndex-1];
95}
96
97/**
98 * Get the current position of the skeleton
99 * @param skeletonIndex the skeleton to read from
100 * @return the current position as defined in the Kinect SDK (w is ignored)
101 */
102Kinect::Point4 Kinect::GetPosition(int skeletonIndex)
103{
104 if (skeletonIndex <= 0 || skeletonIndex > kNumSkeletons)
105 {
106 wpi_setWPIErrorWithContext(ParameterOutOfRange, "Skeleton index must be 1");
107 return Point4();
108 }
109 UpdateData();
110 return m_position[skeletonIndex-1];
111}
112
113/**
114 * Get the quality of the skeleton.
115 * Quality masks are defined in the SkeletonQuality enum
116 * @param skeletonIndex the skeleton to read from
117 * @return the quality value as defined in the Kinect SDK
118 */
119UINT32 Kinect::GetQuality(int skeletonIndex)
120{
121 if (skeletonIndex <= 0 || skeletonIndex > kNumSkeletons)
122 {
123 wpi_setWPIErrorWithContext(ParameterOutOfRange, "Skeleton index must be 1");
124 return kClippedRight | kClippedLeft | kClippedTop | kClippedBottom;
125 }
126 UpdateData();
127 return m_quality[skeletonIndex-1];
128}
129
130/**
131 * Get the TrackingState of the skeleton.
132 * Tracking states are defined in the SkeletonTrackingState enum
133 * @param skeletonIndex the skeleton to read from
134 * @return the tracking state value as defined in the Kinect SDK
135 */
136Kinect::SkeletonTrackingState Kinect::GetTrackingState(int skeletonIndex)
137{
138 if (skeletonIndex <= 0 || skeletonIndex > kNumSkeletons)
139 {
140 wpi_setWPIErrorWithContext(ParameterOutOfRange, "Skeleton index must be 1");
141 return kNotTracked;
142 }
143 UpdateData();
144 return m_trackingState[skeletonIndex-1];
145}
146
147/**
148 * Check for an update of new data from the Driver Station
149 * This will read the new values and update the data structures in this class.
150 */
151void Kinect::UpdateData()
152{
153 Synchronized sync(m_dataLock);
154 UINT32 packetNumber = DriverStation::GetInstance()->GetPacketNumber();
155 if (m_recentPacketNumber != packetNumber)
156 {
157 m_recentPacketNumber = packetNumber;
158 int retVal = getDynamicControlData(kHeaderBundleID, m_rawHeader, sizeof(m_rawHeader), 5);
159 if(retVal == 0)
160 {
161 m_numberOfPlayers = (int)m_rawHeader[13];
162 memcpy(&m_floorClipPlane.x, &m_rawHeader[18], 4);
163 memcpy(&m_floorClipPlane.y, &m_rawHeader[22], 4);
164 memcpy(&m_floorClipPlane.z, &m_rawHeader[26], 4);
165 memcpy(&m_floorClipPlane.w, &m_rawHeader[30], 4);
166 memcpy(&m_gravityNormal.x, &m_rawHeader[34], 4);
167 memcpy(&m_gravityNormal.y, &m_rawHeader[38], 4);
168 memcpy(&m_gravityNormal.z, &m_rawHeader[42], 4);
169 }
170
171 retVal = getDynamicControlData(kSkeletonExtraBundleID, m_rawSkeletonExtra, sizeof(m_rawSkeletonExtra), 5);
172 if(retVal == 0)
173 {
174 memcpy(&m_position[0].x, &m_rawSkeletonExtra[22], 4);
175 memcpy(&m_position[0].y, &m_rawSkeletonExtra[26], 4);
176 memcpy(&m_position[0].z, &m_rawSkeletonExtra[30], 4);
177 memcpy(&m_quality[0], &m_rawSkeletonExtra[34], 4);
178 memcpy(&m_trackingState[0], &m_rawSkeletonExtra[38], 4);
179 }
180
181 retVal = getDynamicControlData(kSkeletonBundleID, m_rawSkeleton, sizeof(m_rawSkeleton), 5);
182 if(retVal == 0)
183 {
184 for(int i=0; i < Skeleton::JointCount; i++)
185 {
186 memcpy(&m_skeletons[0].m_joints[i].x, &m_rawSkeleton[i*12+2], 4);
187 memcpy(&m_skeletons[0].m_joints[i].y, &m_rawSkeleton[i*12+6], 4);
188 memcpy(&m_skeletons[0].m_joints[i].z, &m_rawSkeleton[i*12+10], 4);
189 m_skeletons[0].m_joints[i].trackingState = (Skeleton::JointTrackingState)m_rawSkeletonExtra[i+2];
190 }
191 }
192
193 // TODO: Read skeleton #2
194 }
195}