/*----------------------------------------------------------------------------*/ /* Copyright (c) FIRST 2011. All Rights Reserved. */ /* Open Source Software - may be modified and shared by FRC teams. The code */ /* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ /*----------------------------------------------------------------------------*/ #include "Kinect.h" #include "DriverStation.h" //#include "NetworkCommunication/FRCComm.h" //#include "NetworkCommunication/UsageReporting.h" #include "Skeleton.h" #include "HAL/cpp/Synchronized.hpp" #include "WPIErrors.h" #include #define kHeaderBundleID HALFRC_NetworkCommunication_DynamicType_Kinect_Header #define kSkeletonExtraBundleID HALFRC_NetworkCommunication_DynamicType_Kinect_Extra1 #define kSkeletonBundleID HALFRC_NetworkCommunication_DynamicType_Kinect_Vertices1 Kinect *Kinect::_instance = NULL; Kinect::Kinect() : m_recentPacketNumber(0), m_numberOfPlayers(0) { AddToSingletonList(); m_dataLock = initializeMutexNormal(); HALReport(HALUsageReporting::kResourceType_Kinect, 0); } Kinect::~Kinect() { takeMutex(m_dataLock); deleteMutex(m_dataLock); } /** * Get the one and only Kinect object * @returns pointer to a Kinect */ Kinect *Kinect::GetInstance() { if (_instance == NULL) _instance = new Kinect(); return _instance; } /** * Get the number of tracked players on the Kinect * @return the number of players being actively tracked */ int Kinect::GetNumberOfPlayers() { UpdateData(); return m_numberOfPlayers; } /** * Get the floor clip plane as defined in the Kinect SDK * @return The floor clip plane */ Kinect::Point4 Kinect::GetFloorClipPlane() { UpdateData(); return m_floorClipPlane; } /** * Get the gravity normal from the kinect as defined in the Kinect SDK * @return The gravity normal (w is ignored) */ Kinect::Point4 Kinect::GetGravityNormal() { UpdateData(); return m_gravityNormal; } /** * Get the skeleton data * Returns the detected skeleton data from the kinect as defined in the Kinect SDK * @param skeletonIndex Which of (potentially 2) skeletons to return. This is ignored in this implementation and * only a single skeleton is supported for the FRC release default gesture interpretation. * @return The current version of the skeleton object. */ Skeleton Kinect::GetSkeleton(int skeletonIndex) { if (skeletonIndex <= 0 || skeletonIndex > kNumSkeletons) { wpi_setWPIErrorWithContext(ParameterOutOfRange, "Skeleton index must be 1"); return Skeleton(); } UpdateData(); return m_skeletons[skeletonIndex-1]; } /** * Get the current position of the skeleton * @param skeletonIndex the skeleton to read from * @return the current position as defined in the Kinect SDK (w is ignored) */ Kinect::Point4 Kinect::GetPosition(int skeletonIndex) { if (skeletonIndex <= 0 || skeletonIndex > kNumSkeletons) { wpi_setWPIErrorWithContext(ParameterOutOfRange, "Skeleton index must be 1"); return Point4(); } UpdateData(); return m_position[skeletonIndex-1]; } /** * Get the quality of the skeleton. * Quality masks are defined in the SkeletonQuality enum * @param skeletonIndex the skeleton to read from * @return the quality value as defined in the Kinect SDK */ uint32_t Kinect::GetQuality(int skeletonIndex) { if (skeletonIndex <= 0 || skeletonIndex > kNumSkeletons) { wpi_setWPIErrorWithContext(ParameterOutOfRange, "Skeleton index must be 1"); return kClippedRight | kClippedLeft | kClippedTop | kClippedBottom; } UpdateData(); return m_quality[skeletonIndex-1]; } /** * Get the TrackingState of the skeleton. * Tracking states are defined in the SkeletonTrackingState enum * @param skeletonIndex the skeleton to read from * @return the tracking state value as defined in the Kinect SDK */ Kinect::SkeletonTrackingState Kinect::GetTrackingState(int skeletonIndex) { if (skeletonIndex <= 0 || skeletonIndex > kNumSkeletons) { wpi_setWPIErrorWithContext(ParameterOutOfRange, "Skeleton index must be 1"); return kNotTracked; } UpdateData(); return m_trackingState[skeletonIndex-1]; } /** * Check for an update of new data from the Driver Station * This will read the new values and update the data structures in this class. */ void Kinect::UpdateData() { Synchronized sync(m_dataLock); uint32_t packetNumber = DriverStation::GetInstance()->GetPacketNumber(); if (m_recentPacketNumber != packetNumber) { m_recentPacketNumber = packetNumber; int retVal = HALGetDynamicControlData(kHeaderBundleID, m_rawHeader, sizeof(m_rawHeader), 5); if(retVal == 0) { m_numberOfPlayers = (int)m_rawHeader[13]; memcpy(&m_floorClipPlane.x, &m_rawHeader[18], 4); memcpy(&m_floorClipPlane.y, &m_rawHeader[22], 4); memcpy(&m_floorClipPlane.z, &m_rawHeader[26], 4); memcpy(&m_floorClipPlane.w, &m_rawHeader[30], 4); memcpy(&m_gravityNormal.x, &m_rawHeader[34], 4); memcpy(&m_gravityNormal.y, &m_rawHeader[38], 4); memcpy(&m_gravityNormal.z, &m_rawHeader[42], 4); } retVal = HALGetDynamicControlData(kSkeletonExtraBundleID, m_rawSkeletonExtra, sizeof(m_rawSkeletonExtra), 5); if(retVal == 0) { memcpy(&m_position[0].x, &m_rawSkeletonExtra[22], 4); memcpy(&m_position[0].y, &m_rawSkeletonExtra[26], 4); memcpy(&m_position[0].z, &m_rawSkeletonExtra[30], 4); memcpy(&m_quality[0], &m_rawSkeletonExtra[34], 4); memcpy(&m_trackingState[0], &m_rawSkeletonExtra[38], 4); } retVal = HALGetDynamicControlData(kSkeletonBundleID, m_rawSkeleton, sizeof(m_rawSkeleton), 5); if(retVal == 0) { for(int i=0; i < Skeleton::JointCount; i++) { memcpy(&m_skeletons[0].m_joints[i].x, &m_rawSkeleton[i*12+2], 4); memcpy(&m_skeletons[0].m_joints[i].y, &m_rawSkeleton[i*12+6], 4); memcpy(&m_skeletons[0].m_joints[i].z, &m_rawSkeleton[i*12+10], 4); m_skeletons[0].m_joints[i].trackingState = (Skeleton::JointTrackingState)m_rawSkeletonExtra[i+2]; } } // TODO: Read skeleton #2 } }