$search
00001 // openni_tracker.cpp 00002 00003 #include <ros/ros.h> 00004 #include <ros/package.h> 00005 #include <tf/transform_broadcaster.h> 00006 #include <kdl/frames.hpp> 00007 00008 #include <XnOpenNI.h> 00009 #include <XnCodecIDs.h> 00010 #include <XnCppWrapper.h> 00011 00012 using std::string; 00013 00014 xn::Context g_Context; 00015 xn::DepthGenerator g_DepthGenerator; 00016 xn::UserGenerator g_UserGenerator; 00017 00018 XnBool g_bNeedPose = FALSE; 00019 XnChar g_strPose[20] = ""; 00020 00021 void XN_CALLBACK_TYPE User_NewUser(xn::UserGenerator& generator, XnUserID nId, void* pCookie) { 00022 ROS_INFO("New User %d", nId); 00023 00024 if (g_bNeedPose) 00025 g_UserGenerator.GetPoseDetectionCap().StartPoseDetection(g_strPose, nId); 00026 else 00027 g_UserGenerator.GetSkeletonCap().RequestCalibration(nId, TRUE); 00028 } 00029 00030 void XN_CALLBACK_TYPE User_LostUser(xn::UserGenerator& generator, XnUserID nId, void* pCookie) { 00031 ROS_INFO("Lost user %d", nId); 00032 } 00033 00034 void XN_CALLBACK_TYPE UserCalibration_CalibrationStart(xn::SkeletonCapability& capability, XnUserID nId, void* pCookie) { 00035 ROS_INFO("Calibration started for user %d", nId); 00036 } 00037 00038 void XN_CALLBACK_TYPE UserCalibration_CalibrationEnd(xn::SkeletonCapability& capability, XnUserID nId, XnBool bSuccess, void* pCookie) { 00039 if (bSuccess) { 00040 ROS_INFO("Calibration complete, start tracking user %d", nId); 00041 g_UserGenerator.GetSkeletonCap().StartTracking(nId); 00042 } 00043 else { 00044 ROS_INFO("Calibration failed for user %d", nId); 00045 if (g_bNeedPose) 00046 g_UserGenerator.GetPoseDetectionCap().StartPoseDetection(g_strPose, nId); 00047 else 00048 g_UserGenerator.GetSkeletonCap().RequestCalibration(nId, TRUE); 00049 } 00050 } 00051 00052 void XN_CALLBACK_TYPE UserPose_PoseDetected(xn::PoseDetectionCapability& capability, XnChar const* strPose, XnUserID nId, void* pCookie) { 00053 ROS_INFO("Pose %s detected for user %d", strPose, nId); 00054 g_UserGenerator.GetPoseDetectionCap().StopPoseDetection(nId); 00055 g_UserGenerator.GetSkeletonCap().RequestCalibration(nId, TRUE); 00056 } 00057 00058 void publishTransform(XnUserID const& user, XnSkeletonJoint const& joint, string const& frame_id, string const& child_frame_id) { 00059 static tf::TransformBroadcaster br; 00060 00061 XnSkeletonJointPosition joint_position; 00062 g_UserGenerator.GetSkeletonCap().GetSkeletonJointPosition(user, joint, joint_position); 00063 double x = -joint_position.position.X / 1000.0; 00064 double y = joint_position.position.Y / 1000.0; 00065 double z = joint_position.position.Z / 1000.0; 00066 00067 XnSkeletonJointOrientation joint_orientation; 00068 g_UserGenerator.GetSkeletonCap().GetSkeletonJointOrientation(user, joint, joint_orientation); 00069 00070 XnFloat* m = joint_orientation.orientation.elements; 00071 KDL::Rotation rotation(m[0], m[1], m[2], 00072 m[3], m[4], m[5], 00073 m[6], m[7], m[8]); 00074 double qx, qy, qz, qw; 00075 rotation.GetQuaternion(qx, qy, qz, qw); 00076 00077 char child_frame_no[128]; 00078 snprintf(child_frame_no, sizeof(child_frame_no), "%s_%d", child_frame_id.c_str(), user); 00079 00080 tf::Transform transform; 00081 transform.setOrigin(tf::Vector3(x, y, z)); 00082 transform.setRotation(tf::Quaternion(qx, -qy, -qz, qw)); 00083 00084 // #4994 00085 tf::Transform change_frame; 00086 change_frame.setOrigin(tf::Vector3(0, 0, 0)); 00087 tf::Quaternion frame_rotation; 00088 frame_rotation.setEulerZYX(1.5708, 0, 1.5708); 00089 change_frame.setRotation(frame_rotation); 00090 00091 transform = change_frame * transform; 00092 00093 br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), frame_id, child_frame_no)); 00094 } 00095 00096 void publishTransforms(const std::string& frame_id) { 00097 XnUserID users[15]; 00098 XnUInt16 users_count = 15; 00099 g_UserGenerator.GetUsers(users, users_count); 00100 00101 for (int i = 0; i < users_count; ++i) { 00102 XnUserID user = users[i]; 00103 if (!g_UserGenerator.GetSkeletonCap().IsTracking(user)) 00104 continue; 00105 00106 00107 publishTransform(user, XN_SKEL_HEAD, frame_id, "head"); 00108 publishTransform(user, XN_SKEL_NECK, frame_id, "neck"); 00109 publishTransform(user, XN_SKEL_TORSO, frame_id, "torso"); 00110 00111 publishTransform(user, XN_SKEL_LEFT_SHOULDER, frame_id, "left_shoulder"); 00112 publishTransform(user, XN_SKEL_LEFT_ELBOW, frame_id, "left_elbow"); 00113 publishTransform(user, XN_SKEL_LEFT_HAND, frame_id, "left_hand"); 00114 00115 publishTransform(user, XN_SKEL_RIGHT_SHOULDER, frame_id, "right_shoulder"); 00116 publishTransform(user, XN_SKEL_RIGHT_ELBOW, frame_id, "right_elbow"); 00117 publishTransform(user, XN_SKEL_RIGHT_HAND, frame_id, "right_hand"); 00118 00119 publishTransform(user, XN_SKEL_LEFT_HIP, frame_id, "left_hip"); 00120 publishTransform(user, XN_SKEL_LEFT_KNEE, frame_id, "left_knee"); 00121 publishTransform(user, XN_SKEL_LEFT_FOOT, frame_id, "left_foot"); 00122 00123 publishTransform(user, XN_SKEL_RIGHT_HIP, frame_id, "right_hip"); 00124 publishTransform(user, XN_SKEL_RIGHT_KNEE, frame_id, "right_knee"); 00125 publishTransform(user, XN_SKEL_RIGHT_FOOT, frame_id, "right_foot"); 00126 } 00127 } 00128 00129 #define CHECK_RC(nRetVal, what) \ 00130 if (nRetVal != XN_STATUS_OK) \ 00131 { \ 00132 ROS_ERROR("%s failed: %s", what, xnGetStatusString(nRetVal));\ 00133 return nRetVal; \ 00134 } 00135 00136 int main(int argc, char **argv) { 00137 ros::init(argc, argv, "openni_tracker"); 00138 ros::NodeHandle nh; 00139 00140 string configFilename = ros::package::getPath("openni_tracker") + "/openni_tracker.xml"; 00141 XnStatus nRetVal = g_Context.InitFromXmlFile(configFilename.c_str()); 00142 CHECK_RC(nRetVal, "InitFromXml"); 00143 00144 nRetVal = g_Context.FindExistingNode(XN_NODE_TYPE_DEPTH, g_DepthGenerator); 00145 CHECK_RC(nRetVal, "Find depth generator"); 00146 00147 nRetVal = g_Context.FindExistingNode(XN_NODE_TYPE_USER, g_UserGenerator); 00148 if (nRetVal != XN_STATUS_OK) { 00149 nRetVal = g_UserGenerator.Create(g_Context); 00150 CHECK_RC(nRetVal, "Find user generator"); 00151 } 00152 00153 if (!g_UserGenerator.IsCapabilitySupported(XN_CAPABILITY_SKELETON)) { 00154 ROS_INFO("Supplied user generator doesn't support skeleton"); 00155 return 1; 00156 } 00157 00158 XnCallbackHandle hUserCallbacks; 00159 g_UserGenerator.RegisterUserCallbacks(User_NewUser, User_LostUser, NULL, hUserCallbacks); 00160 00161 XnCallbackHandle hCalibrationCallbacks; 00162 g_UserGenerator.GetSkeletonCap().RegisterCalibrationCallbacks(UserCalibration_CalibrationStart, UserCalibration_CalibrationEnd, NULL, hCalibrationCallbacks); 00163 00164 if (g_UserGenerator.GetSkeletonCap().NeedPoseForCalibration()) { 00165 g_bNeedPose = TRUE; 00166 if (!g_UserGenerator.IsCapabilitySupported(XN_CAPABILITY_POSE_DETECTION)) { 00167 ROS_INFO("Pose required, but not supported"); 00168 return 1; 00169 } 00170 00171 XnCallbackHandle hPoseCallbacks; 00172 g_UserGenerator.GetPoseDetectionCap().RegisterToPoseCallbacks(UserPose_PoseDetected, NULL, NULL, hPoseCallbacks); 00173 00174 g_UserGenerator.GetSkeletonCap().GetCalibrationPose(g_strPose); 00175 } 00176 00177 g_UserGenerator.GetSkeletonCap().SetSkeletonProfile(XN_SKEL_PROFILE_ALL); 00178 00179 nRetVal = g_Context.StartGeneratingAll(); 00180 CHECK_RC(nRetVal, "StartGenerating"); 00181 00182 ros::Rate r(30); 00183 00184 00185 ros::NodeHandle pnh("~"); 00186 string frame_id("openni_depth_frame"); 00187 pnh.getParam("camera_frame_id", frame_id); 00188 00189 while (ros::ok()) { 00190 g_Context.WaitAndUpdateAll(); 00191 publishTransforms(frame_id); 00192 r.sleep(); 00193 } 00194 00195 g_Context.Shutdown(); 00196 return 0; 00197 }