00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "realtime_urdf_filter/urdf_filter.h"
00032 #include "realtime_urdf_filter/urdf_renderer.h"
00033
00034 #include <ros/node_handle.h>
00035 #include <ros/package.h>
00036 #include <tf/transform_broadcaster.h>
00037 #include <tf/tfMessage.h>
00038
00039 #include <std_msgs/String.h>
00040
00041 #include <sstream>
00042
00043 #include <XnOpenNI.h>
00044 #include <XnCodecIDs.h>
00045 #include <XnCppWrapper.h>
00046 #include <XnPropNames.h>
00047
00048 #define CHECK_RC(nRetVal, what) \
00049 if (nRetVal != XN_STATUS_OK) \
00050 { \
00051 printf("%s failed: %s\n", what, xnGetStatusString(nRetVal));\
00052 }
00053
00054
00055 class OpenNITrackerLoopback
00056 {
00057 public:
00058 OpenNITrackerLoopback (ros::NodeHandle &nh, int argc, char **argv)
00059 : g_bNeedPose (false)
00060 , nh_ (nh)
00061 , argc_ (argc), argv_(argv)
00062 {
00063 g_strPose[0] = 0x0;
00064 XnStatus nRetVal = XN_STATUS_OK;
00065
00066 xn::EnumerationErrors errors;
00067
00068 std::string configFilename = ros::package::getPath("realtime_urdf_filter") + "/include/SamplesConfig.xml";
00069 nRetVal = g_Context.InitFromXmlFile(configFilename.c_str(), g_scriptNode, &errors);
00070 if (nRetVal == XN_STATUS_NO_NODE_PRESENT)
00071 {
00072 XnChar strError[1024];
00073 errors.ToString(strError, 1024);
00074 printf("%s\n", strError);
00075
00076 }
00077 else if (nRetVal != XN_STATUS_OK)
00078 {
00079 printf("Open failed: %s\n", xnGetStatusString(nRetVal));
00080
00081 }
00082
00083 nRetVal = g_Context.FindExistingNode(XN_NODE_TYPE_DEPTH, g_DepthGenerator);
00084
00085 if (nRetVal != XN_STATUS_OK)
00086 {
00087 printf("No depth generator found. Using a default one...");
00088 xn::MockDepthGenerator _mockDepth;
00089 nRetVal = mockDepth.Create(g_Context);
00090 CHECK_RC(nRetVal, "Create mock depth");
00091
00092
00093 XnMapOutputMode defaultMode;
00094 defaultMode.nXRes = 320;
00095 defaultMode.nYRes = 240;
00096 defaultMode.nFPS = 30;
00097 nRetVal = mockDepth.SetMapOutputMode(defaultMode);
00098 CHECK_RC(nRetVal, "set default mode");
00099
00100
00101 XnFieldOfView fov;
00102 fov.fHFOV = 1.0225999419141749;
00103 fov.fVFOV = 0.79661567681716894;
00104 nRetVal = mockDepth.SetGeneralProperty(XN_PROP_FIELD_OF_VIEW, sizeof(fov), &fov);
00105 CHECK_RC(nRetVal, "set FOV");
00106
00107 XnUInt32 nDataSize = defaultMode.nXRes * defaultMode.nYRes * sizeof(XnDepthPixel);
00108 XnDepthPixel* pData = (XnDepthPixel*)xnOSCallocAligned(nDataSize, 1, XN_DEFAULT_MEM_ALIGN);
00109
00110 nRetVal = mockDepth.SetData(1, 0, nDataSize, pData);
00111 CHECK_RC(nRetVal, "set empty depth map");
00112
00113 g_DepthGenerator = mockDepth;
00114 }
00115
00116
00117 mockDepth.CreateBasedOn( g_DepthGenerator, "mock-depth" );
00118 g_DepthGenerator.GetMetaData(depthMD);
00119
00120
00121 xn::Query xQuery;
00122 xQuery.AddNeededNode( "mock-depth" );
00123 nRetVal = g_UserGenerator.Create( g_Context, &xQuery );
00124 CHECK_RC(nRetVal, "Find user generator");
00125
00126 XnCallbackHandle hUserCallbacks, hCalibrationComplete, hPoseDetected;
00127 if (!g_UserGenerator.IsCapabilitySupported(XN_CAPABILITY_SKELETON))
00128 {
00129 printf("Supplied user generator doesn't support skeleton\n");
00130
00131 }
00132 nRetVal = g_UserGenerator.RegisterUserCallbacks(User_NewUser, User_LostUser, this, hUserCallbacks);
00133 CHECK_RC(nRetVal, "Register to user callbacks");
00134 nRetVal = g_UserGenerator.GetSkeletonCap().RegisterToCalibrationComplete(UserCalibration_CalibrationComplete, this, hCalibrationComplete);
00135 CHECK_RC(nRetVal, "Register to calibration complete");
00136
00137 if (g_UserGenerator.GetSkeletonCap().NeedPoseForCalibration())
00138 {
00139 g_bNeedPose = TRUE;
00140 if (!g_UserGenerator.IsCapabilitySupported(XN_CAPABILITY_POSE_DETECTION))
00141 {
00142 printf("Pose required, but not supported\n");
00143
00144 }
00145 nRetVal = g_UserGenerator.GetPoseDetectionCap().RegisterToPoseDetected(UserPose_PoseDetected, this, hPoseDetected);
00146 CHECK_RC(nRetVal, "Register to Pose Detected");
00147 g_UserGenerator.GetSkeletonCap().GetCalibrationPose(g_strPose);
00148 }
00149
00150 g_UserGenerator.GetSkeletonCap().SetSkeletonProfile(XN_SKEL_PROFILE_ALL);
00151
00152 nRetVal = g_Context.StartGeneratingAll();
00153 CHECK_RC(nRetVal, "StartGenerating");
00154
00155 tf_pub_ = nh_.advertise<tf::tfMessage> ("/tf_human", 1);
00156 event_pub_ = nh_.advertise<std_msgs::String> ("user_event", 1);
00157
00158 setupURDFSelfFilter ();
00159 }
00160
00161 void setupURDFSelfFilter ()
00162 {
00163 filter = new realtime_urdf_filter::RealtimeURDFFilter (nh_, argc_, argv_);
00164 filter->width_ = 640;
00165 filter->height_ = 480;
00166 filter->initGL ();
00167 }
00168
00169 ~OpenNITrackerLoopback ()
00170 {
00171 g_scriptNode.Release();
00172 g_DepthGenerator.Release();
00173 mockDepth.Release();
00174 g_UserGenerator.Release();
00175 g_Player.Release();
00176 g_Context.Release();
00177 }
00178
00179 void runOnce (void)
00180 {
00181 xn::SceneMetaData sceneMD;
00182 xn::DepthMetaData depthMD_;
00183
00184
00185
00186 g_Context.WaitOneUpdateAll( g_DepthGenerator );
00187
00188
00189 g_DepthGenerator.GetMetaData (depthMD_);
00190 g_DepthGenerator.GetMetaData (depthMD);
00191 depthMD_.MakeDataWritable();
00192 xn::DepthMap& depthMap_ = depthMD_.WritableDepthMap();
00193 xn::DepthMap& depthMap = depthMD.WritableDepthMap();
00194
00195 static float *buffer = 0;
00196 if (buffer == 0)
00197 {
00198 std::cout << "(re)allocating depth buffer" << std::endl;
00199 buffer = (float*) malloc (depthMap.XRes() * depthMap.YRes() * sizeof(float));
00200 }
00201 for (XnUInt y = 0; y < depthMap.YRes(); y++)
00202 {
00203 for (XnUInt x = 0; x < depthMap.XRes(); x++)
00204 {
00205 buffer [x + y * depthMap.XRes()] = depthMap (depthMap.XRes() - x - 1, y) * 0.001;
00206 }
00207 }
00208
00209 float P[12];
00210 P[0] = 585.260; P[1] = 0.0; P[2] = 317.387; P[3] = 0.0;
00211 P[4] = 0.0; P[5] = 585.028; P[6] = 239.264; P[7] = 0.0;
00212 P[8] = 0.0; P[9] = 0.0; P[10] = 1.0; P[11] = 0.0;
00213
00214 double fx = P[0];
00215 double fy = P[5];
00216 double cx = P[2];
00217 double cy = P[6];
00218 double far_plane_ = 8;
00219 double near_plane_ = 0.1;
00220
00221 double glTf[16];
00222 for (unsigned int i = 0; i < 16; ++i)
00223 glTf[i] = 0.0;
00224
00225
00226
00227 glTf[0]= -2.0 * fx / depthMap.XRes();
00228 glTf[5]= 2.0 * fy / depthMap.YRes();
00229
00230 glTf[8]= 2.0 * (0.5 - cx / depthMap.XRes());
00231 glTf[9]= 2.0 * (cy / depthMap.YRes() - 0.5);
00232
00233 glTf[10]= - (far_plane_ + near_plane_) / (far_plane_ - near_plane_);
00234 glTf[14]= -2.0 * far_plane_ * near_plane_ / (far_plane_ - near_plane_);
00235
00236 glTf[11]= -1;
00237
00238
00239 filter->filter ((unsigned char*)buffer, glTf, depthMap.XRes(), depthMap.YRes());
00240
00241 GLfloat* masked_depth = filter->getMaskedDepth();
00242
00243 for (XnUInt y = 0; y < depthMap.YRes(); y++)
00244 {
00245 for (XnUInt x = 0; x < depthMap.XRes(); x++)
00246 {
00247 depthMap_(x, y) = XnDepthPixel (masked_depth[x + y * depthMap.XRes()] * 1000);
00248 }
00249 }
00250
00251 mockDepth.SetData(depthMD_);
00252
00253 publishTransforms (std::string("openni_depth_frame"));
00254 }
00255
00256 void publishEvent (std::string msg, XnUserID nId)
00257 {
00258 std::stringstream ss;
00259 ss << msg << " " << nId;
00260 std_msgs::String out;
00261 out.data = ss.str();
00262 event_pub_.publish (out);
00263 }
00264
00265 static void XN_CALLBACK_TYPE UserPose_PoseDetected(xn::PoseDetectionCapability& capability, const XnChar* strPose, XnUserID nId, void* pCookie)
00266 {
00267 OpenNITrackerLoopback* self = (OpenNITrackerLoopback*) pCookie;
00268 self->g_UserGenerator.GetPoseDetectionCap().StopPoseDetection (nId);
00269 self->g_UserGenerator.GetSkeletonCap().RequestCalibration (nId, true);
00270 self->publishEvent ("calibrating", nId);
00271 }
00272
00273 static void XN_CALLBACK_TYPE UserCalibration_CalibrationEnd (xn::SkeletonCapability& capability, XnUserID nId, XnBool bSuccess, void* pCookie)
00274 {
00275 OpenNITrackerLoopback* self = (OpenNITrackerLoopback*) pCookie;
00276 if (bSuccess)
00277 {
00278 self->g_UserGenerator.GetSkeletonCap().StartTracking (nId);
00279 self->publishEvent ("tracking", nId);
00280 }
00281 else
00282 {
00283 if (self->g_bNeedPose)
00284 {
00285 self->g_UserGenerator.GetPoseDetectionCap().StartPoseDetection (self->g_strPose, nId);
00286 self->publishEvent ("posedetection", nId);
00287 }
00288 else
00289 {
00290 self->g_UserGenerator.GetSkeletonCap().RequestCalibration (nId, true);
00291 self->publishEvent ("calibrating", nId);
00292 }
00293 }
00294 }
00295
00296
00297 static void XN_CALLBACK_TYPE User_LostUser(xn::UserGenerator& generator, XnUserID nId, void* pCookie)
00298 {
00299 OpenNITrackerLoopback* self = (OpenNITrackerLoopback*) pCookie;
00300 XnUInt32 epochTime = 0;
00301 xnOSGetEpochTime(&epochTime);
00302 printf("%d Lost user %d\n", epochTime, nId);
00303 self->publishEvent ("lost", nId);
00304 }
00305
00306
00307 static void XN_CALLBACK_TYPE User_NewUser(xn::UserGenerator& generator, XnUserID nId, void* pCookie)
00308 {
00309 OpenNITrackerLoopback* self = (OpenNITrackerLoopback*) pCookie;
00310 if(nId > 15)
00311 {
00312 XnStatus res = self->g_UserGenerator.GetPoseDetectionCap().StopPoseDetection(nId);
00313 if (res != XN_CALIBRATION_STATUS_OK)
00314 {
00315 std::cout << "Error StopPoseDetection";
00316 }
00317 res = self->g_UserGenerator.GetSkeletonCap().AbortCalibration(nId);
00318 if (res != XN_CALIBRATION_STATUS_OK)
00319 {
00320 std::cout << "Error AbortCalibration";
00321 }
00322 res = self->g_UserGenerator.GetSkeletonCap().StopTracking(nId);
00323 if (res != XN_CALIBRATION_STATUS_OK)
00324 {
00325 std::cout << "Error StopTracking";
00326 }
00327 self->g_UserGenerator.GetPoseDetectionCap().Release();
00328 self->g_UserGenerator.GetSkeletonCap().Release();
00329 return;
00330 }
00331
00332 XnUInt32 epochTime = 0;
00333 xnOSGetEpochTime(&epochTime);
00334 printf("%d New User %d\n", epochTime, nId);
00335 self->publishEvent ("new", nId);
00336
00337 if (self->g_bNeedPose)
00338 {
00339 std::cerr << "starting pose deteciton: " << __FILE__ << " : " << __LINE__ << std::endl;
00340 self->g_UserGenerator.GetPoseDetectionCap().StartPoseDetection(self->g_strPose, nId);
00341 self->publishEvent ("posedetection", nId);
00342 }
00343 else
00344 {
00345 std::cerr << "request calibration: " << __FILE__ << " : " << __LINE__ << std::endl;
00346 self->g_UserGenerator.GetSkeletonCap().RequestCalibration(nId, TRUE);
00347 self->publishEvent ("calibrating", nId);
00348 }
00349 }
00350
00351
00352 static void XN_CALLBACK_TYPE UserCalibration_CalibrationComplete (xn::SkeletonCapability& capability, XnUserID nId, XnCalibrationStatus eStatus, void* pCookie)
00353 {
00354 XnUInt32 epochTime = 0;
00355 xnOSGetEpochTime(&epochTime);
00356 OpenNITrackerLoopback* self = (OpenNITrackerLoopback*) pCookie;
00357 std::cerr << "got here: " << __FILE__ << " : " << __LINE__ << std::endl;
00358 if (eStatus == XN_CALIBRATION_STATUS_OK)
00359 {
00360
00361 printf("%d Calibration complete, start tracking user %d\n", epochTime, nId);
00362 self->g_UserGenerator.GetSkeletonCap().StartTracking(nId);
00363 self->publishEvent ("tracking", nId);
00364 }
00365 else
00366 {
00367
00368 printf("%d Calibration failed for user %d\n", epochTime, nId);
00369 if (self->g_bNeedPose)
00370 {
00371 self->g_UserGenerator.GetPoseDetectionCap().StartPoseDetection(self->g_strPose, nId);
00372 self->publishEvent ("posedetection", nId);
00373 }
00374 else
00375 {
00376 self->g_UserGenerator.GetSkeletonCap().RequestCalibration(nId, TRUE);
00377 self->publishEvent ("calibrating", nId);
00378 }
00379 }
00380 }
00381
00382
00383 void publishTransforms (std::string const& frame_id)
00384 {
00385 XnUserID users[15];
00386 XnUInt16 users_count = 15;
00387 g_UserGenerator.GetUsers (users, users_count);
00388
00389 tf::tfMessage tfs;
00390
00391 for (int i = 0; i < users_count; ++i)
00392 {
00393 XnUserID user = users[i];
00394 if (!g_UserGenerator.GetSkeletonCap().IsTracking (user))
00395 continue;
00396
00397 std::stringstream ss;
00398 std::string user_suffix;
00399 ss << "_" << user;
00400 user_suffix = ss.str ();
00401
00402 std::cerr << "publishTransforms: " << __FILE__ << " : " << __LINE__ << std::endl;
00403
00404 tfs.transforms.push_back (getUserTransform (user, XN_SKEL_HEAD, frame_id, "head" + user_suffix));
00405 tfs.transforms.push_back (getUserTransform (user, XN_SKEL_NECK, frame_id, "neck" + user_suffix));
00406 tfs.transforms.push_back (getUserTransform (user, XN_SKEL_TORSO, frame_id, "torso" + user_suffix));
00407
00408 tfs.transforms.push_back (getUserTransform (user, XN_SKEL_LEFT_SHOULDER, frame_id, "left_shoulder" + user_suffix));
00409 tfs.transforms.push_back (getUserTransform (user, XN_SKEL_LEFT_ELBOW, frame_id, "left_elbow" + user_suffix));
00410 tfs.transforms.push_back (getUserTransform (user, XN_SKEL_LEFT_HAND, frame_id, "left_hand" + user_suffix));
00411
00412 tfs.transforms.push_back (getUserTransform (user, XN_SKEL_RIGHT_SHOULDER, frame_id, "right_shoulder" + user_suffix));
00413 tfs.transforms.push_back (getUserTransform (user, XN_SKEL_RIGHT_ELBOW, frame_id, "right_elbow" + user_suffix));
00414 tfs.transforms.push_back (getUserTransform (user, XN_SKEL_RIGHT_HAND, frame_id, "right_hand" + user_suffix));
00415
00416 tfs.transforms.push_back (getUserTransform (user, XN_SKEL_LEFT_HIP, frame_id, "left_hip" + user_suffix));
00417 tfs.transforms.push_back (getUserTransform (user, XN_SKEL_LEFT_KNEE, frame_id, "left_knee" + user_suffix));
00418 tfs.transforms.push_back (getUserTransform (user, XN_SKEL_LEFT_FOOT, frame_id, "left_foot" + user_suffix));
00419
00420 tfs.transforms.push_back (getUserTransform (user, XN_SKEL_RIGHT_HIP, frame_id, "right_hip" + user_suffix));
00421 tfs.transforms.push_back (getUserTransform (user, XN_SKEL_RIGHT_KNEE, frame_id, "right_knee" + user_suffix));
00422 tfs.transforms.push_back (getUserTransform (user, XN_SKEL_RIGHT_FOOT, frame_id, "right_foot" + user_suffix));
00423 }
00424 tf_pub_.publish (tfs);
00425 }
00426
00427
00428 geometry_msgs::TransformStamped
00429 getUserTransform(XnUserID const& user, XnSkeletonJoint joint, std::string const& frame_id, std::string const& child_frame_id)
00430 {
00431 XnSkeletonJointPosition joint_position;
00432 g_UserGenerator.GetSkeletonCap().GetSkeletonJointPosition(user, joint, joint_position);
00433 double x = -joint_position.position.X / 1000.0;
00434 double y = joint_position.position.Y / 1000.0;
00435 double z = joint_position.position.Z / 1000.0;
00436
00437 XnSkeletonJointOrientation joint_orientation;
00438 g_UserGenerator.GetSkeletonCap().GetSkeletonJointOrientation(user, joint, joint_orientation);
00439
00440 XnFloat* m = joint_orientation.orientation.elements;
00441 btMatrix3x3 mat (m[0], m[1], m[2],
00442 m[3], m[4], m[5],
00443 m[6], m[7], m[8]);
00444 btQuaternion q;
00445 mat.getRotation (q);
00446 q.setY(-q.y());
00447 q.setZ(-q.z());
00448
00449 tf::Transform transform;
00450 transform.setOrigin(tf::Vector3(x, y, z));
00451 transform.setRotation(q);
00452
00453 geometry_msgs::TransformStamped msg;
00454
00455
00456 tf::Transform change_frame;
00457 change_frame.setOrigin(tf::Vector3(0, 0, 0));
00458 tf::Quaternion frame_rotation;
00459 frame_rotation.setRPY(1.5708, 0, 1.5708);
00460 change_frame.setRotation(frame_rotation);
00461
00462 transform = change_frame * transform;
00463
00464 transformStampedTFToMsg (tf::StampedTransform(transform, ros::Time::now(), frame_id, child_frame_id), msg);
00465 return msg;
00466 }
00467
00468 protected:
00469 xn::Context g_Context;
00470 xn::ScriptNode g_scriptNode;
00471 xn::DepthGenerator g_DepthGenerator;
00472 xn::MockDepthGenerator mockDepth;
00473 xn::UserGenerator g_UserGenerator;
00474 xn::Player g_Player;
00475
00476 xn::DepthMetaData depthMD;
00477
00478 XnBool g_bNeedPose;
00479 XnChar g_strPose[20];
00480 realtime_urdf_filter::RealtimeURDFFilter *filter;
00481
00482
00483 ros::NodeHandle nh_;
00484 ros::Publisher tf_pub_;
00485 ros::Publisher event_pub_;
00486
00487
00488 int argc_;
00489 char **argv_;
00490 };
00491
00492
00493
00494 int main (int argc, char **argv)
00495 {
00496 sleep(1);
00497
00498
00499 ros::init (argc, argv, "urdf_filtered_tracker");
00500 ros::NodeHandle nh ("~");
00501
00502 OpenNITrackerLoopback *lo = new OpenNITrackerLoopback (nh, argc, argv);
00503
00504
00505
00506 ros::Rate r(30);
00507
00508 sleep(1);
00509 while (nh.ok())
00510 {
00511 lo->runOnce ();
00512 r.sleep ();
00513 }
00514
00515 return 0;
00516 }
00517
00518