jerrym | f157933 | 2013-02-07 01:56:28 +0000 | [diff] [blame] | 1 | /*----------------------------------------------------------------------------*/
|
| 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 |
|
| 20 | Kinect *Kinect::_instance = NULL;
|
| 21 |
|
| 22 | Kinect::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 |
|
| 32 | Kinect::~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 | */
|
| 42 | Kinect *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 | */
|
| 53 | int 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 | */
|
| 63 | Kinect::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 | */
|
| 73 | Kinect::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 | */
|
| 86 | Skeleton 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 | */
|
| 102 | Kinect::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 | */
|
| 119 | UINT32 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 | */
|
| 136 | Kinect::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 | */
|
| 151 | void 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 | }
|