body_tracker.cpp
Go to the documentation of this file.
00001 /*
00002  *****************************************************************
00003  * Copyright (c) 2015 \n
00004  * Fraunhofer Institute for Manufacturing Engineering
00005  * and Automation (IPA) \n\n
00006  *
00007  *****************************************************************
00008  *
00009  * \note
00010  * Project name: Care-O-bot
00011  * \note
00012  * ROS stack name: cob_people_perception
00013  * \note
00014  * ROS package name: cob_openni2_tracker
00015  *
00016  * \author
00017  * Author: Olha Meyer
00018  * \author
00019  * Supervised by: Richard Bormann
00020  *
00021  * \date Date of creation: 01.11.2014
00022  *
00023  * \brief
00024  * functions for detecting people within a depth image
00025  * current approach: read the current video flow and detect people using OpenNI and NiTE2
00026  *
00027  *****************************************************************
00028  *
00029  * Redistribution and use in source and binary forms, with or without
00030  * modification, are permitted provided that the following conditions are met:
00031  *
00032  * - Redistributions of source code must retain the above copyright
00033  * notice, this list of conditions and the following disclaimer. \n
00034  * - Redistributions in binary form must reproduce the above copyright
00035  * notice, this list of conditions and the following disclaimer in the
00036  * documentation and/or other materials provided with the distribution. \n
00037  * - Neither the name of the Fraunhofer Institute for Manufacturing
00038  * Engineering and Automation (IPA) nor the names of its
00039  * contributors may be used to endorse or promote products derived from
00040  * this software without specific prior written permission. \n
00041  *
00042  * This program is free software: you can redistribute it and/or modify
00043  * it under the terms of the GNU Lesser General Public License LGPL as
00044  * published by the Free Software Foundation, either version 3 of the
00045  * License, or (at your option) any later version.
00046  *
00047  * This program is distributed in the hope that it will be useful,
00048  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00049  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00050  * GNU Lesser General Public License LGPL for more details.
00051  *
00052  * You should have received a copy of the GNU Lesser General Public
00053  * License LGPL along with this program.
00054  * If not, see <http://www.gnu.org/licenses/>.
00055  *
00056  ****************************************************************/
00057 
00058 /*
00059  * Other Copyrights :
00060  *
00061  ********************************************************
00062  *                                                        *
00063  *   PrimeSense NiTE 2.0 - User Viewer Sample             *
00064  *   Copyright (C) 2012 PrimeSense Ltd.                   *
00065  *   (For a license distribution please see               *
00066  *     the package information):                          *
00067  **********************************************************/
00068 
00069 
00070 #if (defined _WIN32)
00071 #define PRIu64 "llu"
00072 #else
00073 #define __STDC_FORMAT_MACROS
00074 #include <inttypes.h>
00075 #endif
00076 
00077 #include "cob_openni2_tracker/body_tracker.h"
00078 //#include <GL/glut.h>
00079 #include <cob_openni2_tracker/NiteSampleUtilities.h>
00080 #include <math.h>
00081 #include <stdio.h>
00082 
00083 //screen and texture measures
00084 #define GL_WIN_SIZE_X   640
00085 #define GL_WIN_SIZE_Y   512
00086 #define TEXTURE_SIZE    256
00087 #define MAX_USERS 10
00088 #define MIN_NUM_CHUNKS(data_size, chunk_size)   ((((data_size)-1) / (chunk_size) + 1))
00089 #define MIN_CHUNKS_SIZE(data_size, chunk_size)  (MIN_NUM_CHUNKS(data_size, chunk_size) * (chunk_size))
00090 
00091 #define USER_MESSAGE(msg) {\
00092                 sprintf(userStatusLabels[user.getId()], "%s", msg);\
00093                 printf("[%08" PRIu64 "] User #%d:\t%s\n", ts, user.getId(), msg);}
00094 
00095 float Colors[][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}, {1, 1, 1}};
00096 bool visibleUsers[MAX_USERS] = {false};
00097 int colorCount = 3;
00098 nite::SkeletonState skeletonStates[MAX_USERS] = {nite::SKELETON_NONE};
00099 char userStatusLabels[MAX_USERS][100] = {{0}};
00100 char generalMessage[100] = {0};
00101 static std::string detector_ = "camera";
00102 
00103 using namespace std;
00104 using namespace message_filters;
00105 
00106 /*
00107  * BodyTracker constructor: loads the parameter on the parameter server and
00108  * advertises subscribes and publishes.
00109  */
00110 BodyTracker::BodyTracker(ros::NodeHandle nh_priv)
00111 :pcl_cloud_(new pcl::PointCloud<pcl::PointXYZRGB>), m_poseUser(0), br_(), nh_(nh_priv)
00112 {
00113         marker_id_ = 0;
00114 
00115         //nh_ = nh_priv;
00116         // Get Tracker Parameters
00117         if(!nh_.getParam("camera_frame_id", cam_frame_)){
00118                 ROS_WARN("tf_prefix was not found on Param Server! See your launch file!");
00119                 nh_.shutdown();
00120                 Finalize();
00121         }
00122 
00123         if(!nh_.getParam("tf_prefix", tf_prefix_)){
00124                 ROS_WARN("tf_prefix was not found on Param Server! See your launch file!");
00125                 nh_.shutdown();
00126                 Finalize();
00127         }
00128 
00129         if(!nh_.getParam("relative_frame", rel_frame_)){
00130                 ROS_WARN("relative_frame was not found on Param Server! See your launch file!");
00131                 nh_.shutdown();
00132                 Finalize();
00133         }
00134 
00135         std::cout << "\n---------------------------\nPeople Tracker Detection Parameters (CAMERA):\n---------------------------\n";
00136         //parameters from a YAML File
00137         nh_.param("drawSkeleton", drawSkeleton_, false);
00138         std::cout << "drawSkeleton = " << drawSkeleton_ << "\n";
00139         nh_.param("drawCenterOfMass", drawCenterOfMass_, false);
00140         std::cout << "drawCenterOfMass = " << drawCenterOfMass_ << "\n";
00141         nh_.param("drawUserName", drawUserName_, true);
00142         std::cout << "drawUserName = " << drawUserName_ << "\n";
00143         nh_.param("drawBoundingBox", drawBoundingBox_, true);
00144         std::cout << "drawBoundingBox = " << drawBoundingBox_ << "\n";
00145         nh_.param("drawBackground", drawBackground_, false);
00146         std::cout << "drawBackground = " << drawBackground_ << "\n";
00147         nh_.param("drawDepth", drawDepth_, false);
00148         std::cout << "drawDepth = " << drawDepth_ << "\n";
00149         nh_.param("drawFrames", drawFrames_, false);
00150         std::cout << "drawFrames = " << drawFrames_ << "\n";
00151         nh_.param("poseTimeoutToExit", poseTimeoutToExit_, 2000);
00152         std::cout << "poseTimeoutToExit = " << poseTimeoutToExit_ << "\n";
00153 
00154         vis_pub_ = nh_.advertise<visualization_msgs::Marker>( "visualization_marker", 10);
00155         pcl_pub_ = nh_.advertise<pcl::PointCloud<pcl::PointXYZ> >("body_tracker_filter", 0);
00156         people_pub_ = nh_.advertise<cob_perception_msgs::People>("people", 0);
00157 
00158         ROS_INFO("Create BodyTracker.\n");
00159         m_pUserTracker = new nite::UserTracker;
00160         pcl_cloud_->points.clear();
00161 
00162         init();
00163 
00164         it_ = new image_transport::ImageTransport(nh_);
00165         image_sub_.registerCallback(boost::bind(&BodyTracker::imageCallback, this, _1));
00166         image_sub_.subscribe(*it_, "/camera/rgb/image_raw", 1);
00167         image_pub_ = it_->advertise("colorimage_out", 1);
00168 
00169         tracked_users_ = new list<nite::UserData>();
00170 }
00171 
00172 
00173 /*
00174  * A callback function for reading and modifying a color video stream.
00175  * Uses a list of currently tracked people.
00176  *
00177  * @param color_image_msg : received sensor message
00178  */
00179 void BodyTracker::imageCallback(const sensor_msgs::ImageConstPtr& color_image_msg)
00180 {
00181         cv_bridge::CvImageConstPtr cv_ptr;
00182 
00183         try
00184         {
00185                 cv_ptr = cv_bridge::toCvShare(color_image_msg, sensor_msgs::image_encodings::BGR8);
00186         }catch (cv_bridge::Exception& e)
00187         {
00188                 ROS_ERROR("PeopleDetection: cv_bridge exception: %s", e.what());
00189                 return;
00190         }
00191         cv::Mat color_image_ = cv_ptr->image;
00192         int height = color_image_msg->height;
00193         int width = color_image_msg->width;
00194 
00195         //if the list of tracked people not empty, proceed drawing
00196         if(!tracked_users_->empty())
00197         {
00198                 for(std::list<nite::UserData>::iterator iter_ = tracked_users_->begin();
00199                                 iter_ != tracked_users_->end(); ++iter_)
00200                 {
00201                         if((*iter_).getCenterOfMass().x != 0 && (*iter_).getCenterOfMass().y != 0 && (*iter_).getCenterOfMass().z != 0)
00202                         {
00203                                 int max_x = width - (*iter_).getBoundingBox().max.x;
00204                                 int max_y = (*iter_).getBoundingBox().max.y;
00205                                 int min_x = width - (*iter_).getBoundingBox().min.x;
00206                                 int min_y = (*iter_).getBoundingBox().min.y;
00207 
00208                                 double center_x = (*iter_).getCenterOfMass().x;
00209                                 double center_y = (*iter_).getCenterOfMass().y;
00210 
00211 
00212                                 int r = 255*Colors[(*iter_).getId() % colorCount][0];
00213                                 int g = 255*Colors[(*iter_).getId() % colorCount][1];
00214                                 int b = 255*Colors[(*iter_).getId() % colorCount][2];
00215 
00216                                 if(drawBoundingBox_)
00217                                 {
00218                                         cv::rectangle(color_image_, cv::Point(min_x, min_y), cv::Point(max_x, max_y) ,
00219                                                         CV_RGB(r, g, b), 2);
00220                                 }
00221 
00222                                 if(drawCenterOfMass_)
00223                                 {
00224                                         cv::circle(color_image_, cv::Point(100, 100), 10, CV_RGB(r, g, b));
00225                                 }
00226                                 if(drawUserName_)
00227                                 {
00228                                         //drawUserName((*iter_), color_image, cv::Point(100, 100));
00229                                 }
00230                         }
00231                 }
00232         }
00233         cv::waitKey(10);
00234         // Output modified video stream
00235         image_pub_.publish(cv_ptr->toImageMsg());
00236 }
00237 
00238 BodyTracker::~BodyTracker()
00239 {
00240         //shutdown node
00241         Finalize();
00242 }
00243 
00244 void BodyTracker::Finalize()
00245 {
00246         ros::spinOnce();
00247         delete[] m_pTexMap_;
00248         delete m_pUserTracker;
00249         device_.close();
00250         nite::NiTE::shutdown();
00251         openni::OpenNI::shutdown();
00252 }
00253 
00254 /*
00255  * Initializes OpenNI and NiTE, loads a camera device and creates a video stream.
00256  */
00257 void BodyTracker::init()
00258 {
00259         m_pTexMap_ = NULL;
00260 
00261         openni::Status rc = openni::OpenNI::initialize();
00262         if (rc != openni::STATUS_OK)
00263         {
00264                 printf("Failed to initialize OpenNI\n%s\n", openni::OpenNI::getExtendedError());
00265                 nh_.shutdown();
00266                 return;
00267         }
00268         const char* device_Uri = openni::ANY_DEVICE;
00269 
00270         rc = device_.open(device_Uri);
00271         if (rc != openni::STATUS_OK)
00272         {
00273                 printf("Failed to open device_\n%s\n", openni::OpenNI::getExtendedError());
00274                 nh_.shutdown();
00275                 return;
00276         }
00277 
00278         rc = depthSensor_.create(device_, openni::SENSOR_DEPTH);
00279         if (rc != openni::STATUS_OK)
00280         {
00281                 printf("Failed to create a video stream \n%s\n", openni::OpenNI::getExtendedError());
00282                 nh_.shutdown();
00283                 return;
00284         }
00285 
00286         nite::NiTE::initialize();
00287         if (m_pUserTracker->create(&device_) != nite::STATUS_OK)
00288         {
00289                 printf(" Get data for NiTE failed\n");
00290                 nh_.shutdown();
00291                 return;
00292         }
00293 }
00294 
00295 /*
00296  * A loop function to track people.
00297  *
00298  * Firstly, it gets the first snapshot of a depth frame,
00299  * does the segmentation of the scene and starts the UserTracker algorithm
00300  * to detect possible users, which are saved in a UserMap. Each User gets specific
00301  * information(i.a. skeleton, position of joints, detected status).
00302  *
00303  * Secondly, it composes a Point Cloud according to the Usermap information
00304  * and publishes it on a given topic.
00305  *
00306  * At last, it goes through all possible users and puts the visible once
00307  * in the tracked_users_ list:
00308  * - If the user becomes visible/tracked, it is added to the list.
00309  * - If the user is lost, it is erased from the list.
00310  * - If the user is already in the list, its data is updated.
00311  *
00312  */
00313 void BodyTracker::runTracker()
00314 {
00315         while(nh_.ok())
00316         {
00317                 if(tracked_users_ == NULL)
00318                 {
00319                         tracked_users_ = new list<nite::UserData>();
00320                 }
00321                 nite::UserTrackerFrameRef userTrackerFrame;
00322                 openni::VideoFrameRef depthFrame;
00323 
00324                 nite::Status rc = m_pUserTracker->readFrame(&userTrackerFrame);
00325                 if (rc != nite::STATUS_OK)
00326                 {
00327                         printf("GetNextData failed\n");
00328                         return;
00329                 }
00330 
00331                 depthFrame = userTrackerFrame.getDepthFrame();
00332 
00333                 if (m_pTexMap_ == NULL)
00334                 {
00335                         // Texture map init
00336                         m_nTexMapX = MIN_CHUNKS_SIZE(depthFrame.getVideoMode().getResolutionX(), TEXTURE_SIZE);
00337                         m_nTexMapY = MIN_CHUNKS_SIZE(depthFrame.getVideoMode().getResolutionY(), TEXTURE_SIZE);
00338                         m_pTexMap_ = new openni::RGB888Pixel[m_nTexMapX * m_nTexMapY];
00339                 }
00340                 const nite::UserMap& userLabels = userTrackerFrame.getUserMap();
00341 
00342                 if (depthFrame.isValid() && drawDepth_)
00343                 {
00344                         calculateHistogram(m_pDepthHist, MAX_DEPTH, depthFrame);
00345                 }
00346                 memset(m_pTexMap_, 0, m_nTexMapX*m_nTexMapY*sizeof(openni::RGB888Pixel));
00347                 float factor[3] = {1, 1, 1};
00348 
00349                 //construct pcl
00350                 if (depthFrame.isValid() && drawDepth_)
00351                 {
00352                         const nite::UserId* pLabels = userLabels.getPixels();
00353 
00354                         const openni::DepthPixel* pDepthRow = (const openni::DepthPixel*)depthFrame.getData();
00355                         openni::RGB888Pixel* pTexRow = m_pTexMap_ + depthFrame.getCropOriginY() * m_nTexMapX;
00356                         int rowSize = depthFrame.getStrideInBytes() / sizeof(openni::DepthPixel);
00357                         float dX, dY, dZ;
00358 
00359                         pcl_cloud_->resize(depthFrame.getHeight()*depthFrame.getWidth());
00360                         pcl_cloud_->width = depthFrame.getWidth();
00361                         pcl_cloud_->height = depthFrame.getHeight();
00362 
00363                         for (int y = 0; y < depthFrame.getHeight(); ++y)
00364                         {
00365                                 const openni::DepthPixel* pDepth = pDepthRow;
00366                                 openni::RGB888Pixel* pTex = pTexRow + depthFrame.getCropOriginX();
00367 
00368                                 for (int x = 0; x < depthFrame.getWidth(); ++x, ++pDepth, ++pTex, ++pLabels)
00369                                 {
00370                                         if (*pLabels == 0)  // determine color
00371                                         {
00372                                                 if (!drawBackground_)
00373                                                 {
00374                                                         factor[0] = factor[1] = factor[2] = 0;
00375                                                 }
00376                                                 else
00377                                                 {
00378                                                         factor[0] = Colors[colorCount][0];
00379                                                         factor[1] = Colors[colorCount][1];
00380                                                         factor[2] = Colors[colorCount][2];
00381                                                 }
00382                                         }
00383                                         else
00384                                         {
00385                                                 //determin color for users
00386                                                 factor[0] = Colors[*pLabels % colorCount][0];
00387                                                 factor[1] = Colors[*pLabels % colorCount][1];
00388                                                 factor[2] = Colors[*pLabels % colorCount][2];
00389                                         }
00390 
00391                                         if(*pDepth != 0)
00392                                                 openni::CoordinateConverter::convertDepthToWorld(depthSensor_, (float)x, (float)y, (float)(*pDepth), &dX, &dY, &dZ);
00393                                         else
00394                                                 dX = dY = dZ = 0.f;
00395                                         pcl::PointXYZRGB& point = pcl_cloud_->at(x,y);
00396                                         point.r = 255*factor[0];
00397                                         point.g = 255*factor[1];
00398                                         point.b = 255*factor[2];
00399                                         point.x = dZ/1000;
00400                                         point.y = -dX/1000;
00401                                         point.z = dY/1000;
00402 
00403                                         if (*pDepth != 0)
00404                                         {
00405                                                 int nHistValue = m_pDepthHist[*pDepth];
00406                                                 pTex->r = nHistValue*factor[0];
00407                                                 pTex->g = nHistValue*factor[1];
00408                                                 pTex->b = nHistValue*factor[2];
00409 
00410                                                 factor[0] = factor[1] = factor[2] = 1;
00411                                         }
00412                                 }
00413                                 pDepthRow += rowSize;
00414                                 pTexRow += m_nTexMapX;
00415                         }
00416                 }
00417                 //publish pcl
00418                 drawPointCloud();
00419 
00420                 //go through possible users (all that have been detected)
00421                 const nite::Array<nite::UserData>& users = userTrackerFrame.getUsers();
00422                 for (int i = 0; i < users.getSize(); ++i)
00423                 {
00424                         const nite::UserData& user = users[i];
00425                         updateUserState(user, userTrackerFrame.getTimestamp());
00426 
00427                         if(user.isNew())
00428                         {
00429                                 m_pUserTracker->startSkeletonTracking(user.getId());
00430                                 m_pUserTracker->startPoseDetection(user.getId(), nite::POSE_CROSSED_HANDS);
00431                         }
00432                         else if(!user.isLost() && users[i].getSkeleton().getState() == nite::SKELETON_TRACKED)
00433                         {
00434                                 //drawSkeleton(m_pUserTracker, user);
00435 
00436                                 if(drawFrames_)
00437                                 {
00438                                         drawFrames(user);
00439                                 }
00440 
00441                                 double length = sqrt(users[i].getCenterOfMass().x) + sqrt(users[i].getCenterOfMass().y) +
00442                                                 sqrt(users[i].getCenterOfMass().z);
00443                                 //if the user is valid (no empty information)
00444                                 if(length != 0)
00445                                 {
00446                                         //if the user in the list and valid, prepare list for update and
00447                                         //erase user
00448                                         bool found = false;
00449                                         for(std::list<nite::UserData>::iterator iter_ = tracked_users_->begin();
00450                                                         iter_ != tracked_users_->end(); ++iter_)
00451                                         {
00452                                                 if((*iter_).getId() == user.getId())
00453                                                 {
00454                                                         found = true;
00455                                                         tracked_users_->erase(iter_++);
00456                                                         //printf("erase: [");
00457                                                         //for (list<nite::UserData>::iterator iter =tracked_users_->begin();iter !=tracked_users_->end(); ++iter) {
00458                                                         //printf("%i ,", (unsigned int) (*iter).getId());
00459                                                         //}
00460                                                 }
00461                                         }
00462                                         //list waits for update
00463                                         if(found)
00464                                         {
00465                                                 //save updated data for a user in the list
00466                                                 tracked_users_->insert(tracked_users_->begin(), users[i]);
00467                                         }
00468                                         //if the user is valid and has not been in the list jet,
00469                                         //insert the user to the list
00470                                         if(!found || tracked_users_->empty())
00471                                         {
00472                                                 tracked_users_->insert(tracked_users_->end(), users[i]);
00473                                         }
00474                                 }
00475                         }
00476                         else if(user.isLost())
00477                         {
00478                                 //delete user out of the list
00479                                 for(std::list<nite::UserData>::iterator iter_ = tracked_users_->begin();
00480                                                 iter_ != tracked_users_->end(); ++iter_)
00481                                 {
00482                                         if((*iter_).getId() ==  user.getId())
00483                                                 tracked_users_->erase(iter_++);
00484                                 }
00485                         }
00486 
00487                         if (m_poseUser == 0 || m_poseUser == user.getId())
00488                         {
00489                                 const nite::PoseData& pose = user.getPose(nite::POSE_CROSSED_HANDS);
00490                                 if (pose.isEntered())
00491                                 {
00492                                         // Start timer
00493                                         sprintf(generalMessage, "In exit pose. Keep it for %d second%s to exit\n", poseTimeoutToExit_/1000, poseTimeoutToExit_/1000 == 1 ? "" : "s");
00494                                         printf("Waiting to start timeout %i \n", poseTimeoutToExit_/1000);
00495                                         m_poseUser = user.getId();
00496                                         m_poseTime_ = userTrackerFrame.getTimestamp();
00497                                 }
00498                                 else if (pose.isExited())
00499                                 {
00500                                         memset(generalMessage, 0, sizeof(generalMessage));
00501                                         m_poseTime_ = 0;
00502                                         m_poseUser = 0;
00503                                 }
00504                                 else if (pose.isHeld())
00505                                 {
00506                                         if (userTrackerFrame.getTimestamp() - m_poseTime_ > poseTimeoutToExit_ * 1000)
00507                                         {
00508                                                 printf("Timeout.");
00509                                         }
00510                                 }
00511                         }
00512                 }
00513                 publishTrackedUserMsg();
00514         }
00515 }
00516 /*
00517  * Publishes user message [@cob_perception_msgs::Person] on the given topic of [@people_pub] publisher.
00518  */
00519 void BodyTracker::publishTrackedUserMsg()
00520 {
00521         //publish tracked users
00522         std::vector<cob_perception_msgs::Person> detected_people;
00523         for(std::list<nite::UserData>::iterator iter_ = tracked_users_->begin(); iter_ != tracked_users_->end(); ++iter_)
00524         {
00525                 cob_perception_msgs::Person person;
00526                 cob_perception_msgs::Skeleton skeleton;
00527 
00528                 skeleton.joints.push_back(convertNiteJointToMsgs((*iter_).getSkeleton().getJoint(nite::JOINT_HEAD)));
00529                 skeleton.joints.push_back(convertNiteJointToMsgs((*iter_).getSkeleton().getJoint(nite::JOINT_NECK)));
00530                 skeleton.joints.push_back(convertNiteJointToMsgs((*iter_).getSkeleton().getJoint(nite::JOINT_LEFT_SHOULDER)));
00531                 skeleton.joints.push_back(convertNiteJointToMsgs((*iter_).getSkeleton().getJoint(nite::JOINT_RIGHT_SHOULDER)));
00532                 skeleton.joints.push_back(convertNiteJointToMsgs((*iter_).getSkeleton().getJoint(nite::JOINT_LEFT_ELBOW)));
00533                 skeleton.joints.push_back(convertNiteJointToMsgs((*iter_).getSkeleton().getJoint(nite::JOINT_RIGHT_ELBOW)));
00534                 skeleton.joints.push_back(convertNiteJointToMsgs((*iter_).getSkeleton().getJoint(nite::JOINT_LEFT_HAND)));
00535                 skeleton.joints.push_back(convertNiteJointToMsgs((*iter_).getSkeleton().getJoint(nite::JOINT_RIGHT_HAND)));
00536                 skeleton.joints.push_back(convertNiteJointToMsgs((*iter_).getSkeleton().getJoint(nite::JOINT_TORSO)));
00537                 skeleton.joints.push_back(convertNiteJointToMsgs((*iter_).getSkeleton().getJoint(nite::JOINT_LEFT_HIP)));
00538                 skeleton.joints.push_back(convertNiteJointToMsgs((*iter_).getSkeleton().getJoint(nite::JOINT_RIGHT_HIP)));
00539                 skeleton.joints.push_back(convertNiteJointToMsgs((*iter_).getSkeleton().getJoint(nite::JOINT_LEFT_KNEE)));
00540                 skeleton.joints.push_back(convertNiteJointToMsgs((*iter_).getSkeleton().getJoint(nite::JOINT_RIGHT_KNEE)));
00541                 skeleton.joints.push_back(convertNiteJointToMsgs((*iter_).getSkeleton().getJoint(nite::JOINT_LEFT_FOOT)));
00542                 skeleton.joints.push_back(convertNiteJointToMsgs((*iter_).getSkeleton().getJoint(nite::JOINT_RIGHT_FOOT)));
00543 
00544                 char id[100];
00545                 snprintf(id,100,"person %d", (*iter_).getId());
00546                 string id_ = std::string(id);
00547 
00548                 person.name = id_;
00549                 person.detector = detector_;
00550                 person.position.position.x = (*iter_).getCenterOfMass().x/1000.0;
00551                 person.position.position.y = -(*iter_).getCenterOfMass().y/1000.0;
00552                 person.position.position.z = (*iter_).getCenterOfMass().z/1000.0;
00553 
00554                 person.skeleton = skeleton;
00555 
00556                 unsigned int length = sqrt(person.position.position.x) + sqrt(person.position.position.y) +
00557                                 sqrt(person.position.position.z);
00558 
00559                 //save only valid data and no empty points
00560                 if(length != 0)
00561                         detected_people.push_back(person);
00562         }
00563         cob_perception_msgs::People array;
00564         array.header.stamp = ros::Time::now();
00565         array.header.frame_id = rel_frame_;
00566         array.people = detected_people;
00567         people_pub_.publish(array);
00568 
00569 }
00570 /*
00571  * Updates and prints the user information.
00572  */
00573 void BodyTracker::updateUserState(const nite::UserData& user, uint64_t ts)
00574 {
00575         if(user.isNew()){
00576                 USER_MESSAGE("New User detected.");
00577         }
00578         else if(user.isVisible() && !visibleUsers[user.getId()]){
00579                 printf("[%08" PRIu64 "] User #%d:\tVisible\n", ts, user.getId());
00580         }
00581         else if(!user.isVisible() && visibleUsers[user.getId()]){
00582                 printf("[%08" PRIu64 "] User #%d:\tOut of Scene\n", ts, user.getId());
00583         }
00584         else if(user.isLost()){
00585                 USER_MESSAGE("Lost");
00586         }
00587         visibleUsers[user.getId()] = user.isVisible();
00588 
00589         if(skeletonStates[user.getId()] != user.getSkeleton().getState())
00590         {
00591                 switch(skeletonStates[user.getId()] = user.getSkeleton().getState())
00592                 {
00593                 case nite::SKELETON_NONE:
00594                         USER_MESSAGE("Stopped tracking !")
00595                         break;
00596                 case nite::SKELETON_CALIBRATING:
00597                         USER_MESSAGE("Calibrating...")
00598                         break;
00599                 case nite::SKELETON_TRACKED:
00600                         USER_MESSAGE("Tracking ...");
00601                         break;
00602                 case nite::SKELETON_CALIBRATION_ERROR_NOT_IN_POSE:
00603                 case nite::SKELETON_CALIBRATION_ERROR_HANDS:
00604                 case nite::SKELETON_CALIBRATION_ERROR_LEGS:
00605                 case nite::SKELETON_CALIBRATION_ERROR_HEAD:
00606                 case nite::SKELETON_CALIBRATION_ERROR_TORSO:
00607                         USER_MESSAGE("Calibration Failed... :-|")
00608                         break;
00609                 }
00610         }
00611 }
00612 
00613 /*
00614  * Publishes joints on TF.
00615  */
00616 void BodyTracker::publishJoints(ros::NodeHandle& nh, tf::TransformBroadcaster& br, std::string joint_name,
00617                 nite::SkeletonJoint joint, std::string tf_prefix, std::string rel_frame, int id){
00618 
00619         if (joint.getPositionConfidence() > 0.0)
00620         {
00621                 tf::Transform transform;
00622                 transform.setOrigin(tf::Vector3(joint.getPosition().x/1000.0, -joint.getPosition().y/1000.0,
00623                                 joint.getPosition().z/1000.0));
00624                 tf::Quaternion frame_rotation;
00625                 frame_rotation.setEuler(0, 0, 0);
00626                 transform.setRotation(frame_rotation);
00627                 std::stringstream frame_id_stream;
00628                 std::string frame_id;
00629                 frame_id_stream << "/" << tf_prefix << "/user_" << id << "/" << joint_name;
00630                 frame_id = frame_id_stream.str();
00631                 // std::cout << frame_id << std::endl;
00632                 br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), rel_frame, frame_id));
00633         }
00634 }
00635 
00636 /*
00637  * Converts a nite message to a geometry message.
00638  */
00639 geometry_msgs::Pose BodyTracker::convertNiteJointToMsgs(nite::SkeletonJoint joint)
00640 {
00641         geometry_msgs::Pose transform_msgs;
00642 
00643         if (joint.getPositionConfidence() > 0.0)
00644         {
00645                 tf::Transform transform;
00646                 transform.setOrigin(tf::Vector3(joint.getPosition().x/1000.0, -joint.getPosition().y/1000.0,
00647                                 joint.getPosition().z/1000.0));
00648                 tf::Quaternion frame_rotation;
00649                 frame_rotation.setEuler(0, 0, 0);
00650                 transform.setRotation(frame_rotation);
00651                 tf::poseTFToMsg(transform, transform_msgs);
00652         }
00653         return transform_msgs;
00654 }
00655 
00656 /*
00657  * Draws a Point Cloud. Resets the points of a [@pcl_cloud].
00658  */
00659 void BodyTracker::drawPointCloud()
00660 {
00661         ros::Time time = ros::Time::now();
00662         uint64_t st = time.toNSec();
00663         pcl_cloud_->header.stamp = st;
00664         pcl_cloud_->header.frame_id = cam_frame_;
00665 
00666         pcl_pub_.publish(pcl_cloud_);
00667         pcl_cloud_->points.clear();
00668 }
00669 /*
00670  * Draws the limbs of a person on an image view.
00671  */
00672 void BodyTracker::drawLimb(nite::UserTracker* pUserTracker, const nite::SkeletonJoint& joint1, const nite::SkeletonJoint& joint2, int color)
00673 {
00674         //TO DO: compose limbs for drawing function
00675 }
00676 /*
00677  * Draws a skeleton on an image view.
00678  */
00679 void BodyTracker::drawSkeleton(nite::UserTracker* pUserTracker, const nite::UserData& userData)
00680 {
00681         //      drawLimb(pUserTracker, userData.getSkeleton().getJoint(nite::JOINT_HEAD), userData.getSkeleton().getJoint(nite::JOINT_NECK), userData.getId() % colorCount);
00682         //      drawLimb(pUserTracker, userData.getSkeleton().getJoint(nite::JOINT_LEFT_SHOULDER), userData.getSkeleton().getJoint(nite::JOINT_LEFT_ELBOW), userData.getId() % colorCount);
00683         //      drawLimb(pUserTracker, userData.getSkeleton().getJoint(nite::JOINT_LEFT_ELBOW), userData.getSkeleton().getJoint(nite::JOINT_LEFT_HAND), userData.getId() % colorCount);
00684         //      drawLimb(pUserTracker, userData.getSkeleton().getJoint(nite::JOINT_RIGHT_SHOULDER), userData.getSkeleton().getJoint(nite::JOINT_RIGHT_ELBOW), userData.getId() % colorCount);
00685         //      drawLimb(pUserTracker, userData.getSkeleton().getJoint(nite::JOINT_RIGHT_ELBOW), userData.getSkeleton().getJoint(nite::JOINT_RIGHT_HAND), userData.getId() % colorCount);
00686         //      drawLimb(pUserTracker, userData.getSkeleton().getJoint(nite::JOINT_LEFT_SHOULDER), userData.getSkeleton().getJoint(nite::JOINT_RIGHT_SHOULDER), userData.getId() % colorCount);
00687         //      drawLimb(pUserTracker, userData.getSkeleton().getJoint(nite::JOINT_LEFT_SHOULDER), userData.getSkeleton().getJoint(nite::JOINT_TORSO), userData.getId() % colorCount);
00688         //      drawLimb(pUserTracker, userData.getSkeleton().getJoint(nite::JOINT_RIGHT_SHOULDER), userData.getSkeleton().getJoint(nite::JOINT_TORSO), userData.getId() % colorCount);
00689         //      drawLimb(pUserTracker, userData.getSkeleton().getJoint(nite::JOINT_TORSO), userData.getSkeleton().getJoint(nite::JOINT_LEFT_HIP), userData.getId() % colorCount);
00690         //      drawLimb(pUserTracker, userData.getSkeleton().getJoint(nite::JOINT_TORSO), userData.getSkeleton().getJoint(nite::JOINT_RIGHT_HIP), userData.getId() % colorCount);
00691         //      drawLimb(pUserTracker, userData.getSkeleton().getJoint(nite::JOINT_LEFT_HIP), userData.getSkeleton().getJoint(nite::JOINT_RIGHT_HIP), userData.getId() % colorCount);
00692         //      drawLimb(pUserTracker, userData.getSkeleton().getJoint(nite::JOINT_LEFT_HIP), userData.getSkeleton().getJoint(nite::JOINT_LEFT_KNEE), userData.getId() % colorCount);
00693         //      drawLimb(pUserTracker, userData.getSkeleton().getJoint(nite::JOINT_LEFT_KNEE), userData.getSkeleton().getJoint(nite::JOINT_LEFT_FOOT), userData.getId() % colorCount);
00694         //      drawLimb(pUserTracker, userData.getSkeleton().getJoint(nite::JOINT_RIGHT_HIP), userData.getSkeleton().getJoint(nite::JOINT_RIGHT_KNEE), userData.getId() % colorCount);
00695         //      drawLimb(pUserTracker, userData.getSkeleton().getJoint(nite::JOINT_RIGHT_KNEE), userData.getSkeleton().getJoint(nite::JOINT_RIGHT_FOOT), userData.getId() % colorCount);
00696 
00697         //TO DO: draw skeleton on image view
00698 }
00699 
00700 /*
00701  * Writes down a label on an image view
00702  */
00703 void BodyTracker::drawUserName(const nite::UserData& user, cv::Mat& color_image, cv::Point& tag_coords)
00704 {
00705         //
00706         //      std::string tag_label = "User" + user.getId();
00707         //      std::cout << "The text tag reads: " << tag_label << "." << std::endl;
00708         //      cv::putText(color_image, tag_label, tag_coords, cv::FONT_HERSHEY_PLAIN, 3, CV_RGB(0,0,255), 2);
00709 
00710         //TO DO: write down a label on image view
00711 
00712 }
00713 /*
00714  * Publishes frames and joints markers on TF.
00715  */
00716 void BodyTracker::drawFrames(const nite::UserData& user)
00717 {
00718         int r = 255*Colors[user.getId() % colorCount][0];
00719         int g = 255*Colors[user.getId() % colorCount][1];
00720         int b = 255*Colors[user.getId() % colorCount][2];
00721 
00722         JointMap joints;
00723         joints["head"] = (user.getSkeleton().getJoint(nite::JOINT_HEAD));
00724         joints["neck"] = (user.getSkeleton().getJoint(nite::JOINT_NECK));
00725         joints["left_shoulder"] = (user.getSkeleton().getJoint(nite::JOINT_LEFT_SHOULDER));
00726         joints["right_shoulder"] = (user.getSkeleton().getJoint(nite::JOINT_RIGHT_SHOULDER));
00727         joints["left_elbow"] = (user.getSkeleton().getJoint(nite::JOINT_LEFT_ELBOW));
00728         joints["right_elbow"] = (user.getSkeleton().getJoint(nite::JOINT_RIGHT_ELBOW));
00729         joints["left_hand"] = (user.getSkeleton().getJoint(nite::JOINT_LEFT_HAND));
00730         joints["right_hand"] = (user.getSkeleton().getJoint(nite::JOINT_RIGHT_HAND));
00731         joints["torso"] = (user.getSkeleton().getJoint(nite::JOINT_TORSO));
00732         joints["left_hip"] = (user.getSkeleton().getJoint(nite::JOINT_LEFT_HIP));
00733         joints["right_hip"] = (user.getSkeleton().getJoint(nite::JOINT_RIGHT_HIP));
00734         joints["left_knee"] = (user.getSkeleton().getJoint(nite::JOINT_LEFT_KNEE));
00735         joints["right_knee"] = (user.getSkeleton().getJoint(nite::JOINT_RIGHT_KNEE));
00736         joints["left_foot"] = (user.getSkeleton().getJoint(nite::JOINT_LEFT_FOOT));
00737         joints["right_foot"] = (user.getSkeleton().getJoint(nite::JOINT_RIGHT_FOOT));
00738 
00739         for (JointMap::iterator it=joints.begin(); it!=joints.end(); ++it){
00740                 publishJoints(nh_, br_, it->first, it->second, tf_prefix_, rel_frame_, user.getId());
00741         }
00742 
00743         drawCircle(r, g, b, joints["head"].getPosition());
00744         drawCircle(r, g, b, joints["right_hand"].getPosition());
00745         drawCircle(r, g, b, joints["left_hand"].getPosition());
00746         drawCircle(r, g, b, joints["right_foot"].getPosition());
00747         drawCircle(r, g, b, joints["left_foot"].getPosition());
00748 
00749         drawLine(r, g, b, joints["head"].getPosition(), joints["neck"].getPosition());
00750         drawLine(r, g, b, joints["neck"].getPosition(), joints["left_shoulder"].getPosition());
00751         drawLine(r, g, b, joints["neck"].getPosition(), joints["right_shoulder"].getPosition());
00752         drawLine(r, g, b, joints["right_shoulder"].getPosition(), joints["right_elbow"].getPosition());
00753         drawLine(r, g, b, joints["left_shoulder"].getPosition(), joints["left_elbow"].getPosition());
00754         drawLine(r, g, b, joints["right_elbow"].getPosition(), joints["right_hand"].getPosition());
00755         drawLine(r, g, b, joints["left_elbow"].getPosition(), joints["left_hand"].getPosition());
00756         drawLine(r, g, b, joints["neck"].getPosition(), joints["torso"].getPosition());
00757         drawLine(r, g, b, joints["torso"].getPosition(), joints["left_hip"].getPosition());
00758         drawLine(r, g, b, joints["torso"].getPosition(), joints["right_hip"].getPosition());
00759         drawLine(r, g, b, joints["right_hip"].getPosition(), joints["right_knee"].getPosition());
00760         drawLine(r, g, b, joints["left_hip"].getPosition(), joints["left_knee"].getPosition());
00761         drawLine(r, g, b, joints["right_knee"].getPosition(), joints["right_foot"].getPosition());
00762         drawLine(r, g, b, joints["left_knee"].getPosition(), joints["left_foot"].getPosition());
00763 
00764 }
00765 
00769 void BodyTracker::drawLine (const double r, const double g, const double b,
00770                 const nite::Point3f& pose_start, const nite::Point3f& pose_end )
00771 {
00772         visualization_msgs::Marker marker;
00773         marker.header.frame_id = rel_frame_;
00774         marker.header.stamp = ros::Time::now();
00775         marker.action = visualization_msgs::Marker::ADD;
00776         marker.type = visualization_msgs::Marker::LINE_STRIP;
00777         geometry_msgs::Point p;
00778         marker.id = marker_id_;
00779         p.x = pose_start.x/1000.0;
00780         p.y = -pose_start.y/1000.0;
00781         p.z = pose_start.z/1000.0;
00782         marker.points.push_back(p);
00783         p.x =pose_end.x/1000.0;
00784         p.y = pose_end.y/1000.0;
00785         p.z = pose_end.z/1000.0;
00786         marker.points.push_back(p);
00787         marker.scale.x = 0.019;
00788         marker.scale.y = 0.0;
00789         marker.scale.z = 0.0;
00790         marker.color.r = r;
00791         marker.color.g = g;
00792         marker.color.b = b;
00793         marker.lifetime = ros::Duration(0.01);
00794         vis_pub_.publish(marker);
00795         marker_id_++;
00796 }
00797 
00798 /*
00799  * A helper function to draw circles in rviz
00800  */
00801 
00802 void BodyTracker::drawCircle(const double r, const double g, const double b,
00803                 const nite::Point3f& pose){
00804         visualization_msgs::Marker m;
00805         m.header.stamp = ros::Time::now();
00806         m.action = visualization_msgs::Marker::ADD;
00807         m.header.frame_id = "/camra_link";
00808         m.type = m.SPHERE;
00809         m.id = marker_id_;
00810         m.pose.position.x = pose.x/1000.0;
00811         m.pose.position.y = -pose.y/1000.0;
00812         m.pose.position.z = pose.z/1000.0;
00813         m.scale.x = .1;
00814         m.scale.y = .1;
00815         m.scale.z = .1;
00816         m.color.r = 1;
00817         m.lifetime = ros::Duration(0.01);
00818         vis_pub_.publish(m);
00819         marker_id_++;
00820 }
00821 
00822 void BodyTracker::calculateHistogram(float* pHistogram, int histogramSize, const openni::VideoFrameRef& depthFrame)
00823 {
00824         const openni::DepthPixel* pDepth = (const openni::DepthPixel*)depthFrame.getData();
00825         int width = depthFrame.getWidth();
00826         int height = depthFrame.getHeight();
00827         // Calculate the accumulative histogram (the yellow display...)
00828         memset(pHistogram, 0, histogramSize*sizeof(float));
00829         int restOfRow = depthFrame.getStrideInBytes() / sizeof(openni::DepthPixel) - width;
00830 
00831         unsigned int nNumberOfPoints = 0;
00832         for (int y = 0; y < height; ++y)
00833         {
00834                 for (int x = 0; x < width; ++x, ++pDepth)
00835                 {
00836                         if (*pDepth != 0)
00837                         {
00838                                 pHistogram[*pDepth]++;
00839                                 nNumberOfPoints++;
00840                         }
00841                 }
00842                 pDepth += restOfRow;
00843         }
00844         for (int nIndex=1; nIndex<histogramSize; nIndex++)
00845         {
00846                 pHistogram[nIndex] += pHistogram[nIndex-1];
00847         }
00848         if (nNumberOfPoints)
00849         {
00850                 for (int nIndex=1; nIndex<histogramSize; nIndex++)
00851                 {
00852                         pHistogram[nIndex] = (256 * (1.0f - (pHistogram[nIndex] / nNumberOfPoints)));
00853                 }
00854         }
00855 }
00856 
00857 int main(int argc, char** argv)
00858 {
00859         ros::init(argc, argv, "cob_body_tracker");
00860         ros::NodeHandle nh_priv("~");
00861         BodyTracker BodyTracker(nh_priv);
00862 
00863         ros::spin();
00864         return 0;
00865 
00866 }


cob_openni2_tracker
Author(s): Marcus Liebhardt , Olha Meyer
autogenerated on Fri Aug 28 2015 10:24:08