openni_pointer.cpp
Go to the documentation of this file.
00001 // openni_pointer.cpp
00002 #include <ros/ros.h>
00003 #include <ros/package.h>
00004 #include <std_msgs/UInt8.h>
00005 #include <tf/transform_broadcaster.h>
00006 
00007 #include <XnOpenNI.h>
00008 #include <XnCppWrapper.h>
00009 #include <XnHash.h>
00010 #include <XnLog.h>
00011 
00012 // Header for NITE
00013 #include <XnVNite.h>
00014 #include <XnVPointControl.h>
00015 using std::string;
00016 xn::Context g_Context;
00017 xn::DepthGenerator g_DepthGenerator;
00018 xn::HandsGenerator g_HandsGenerator;
00019 
00020 // NITE objects
00021 XnVSessionManager *g_pSessionManager;
00022 XnVFlowRouter *g_pFlowRouter;
00023 
00024 //
00025 ros::Publisher hand_point_pub_;
00026 ros::Publisher hand_point_status_pub_;
00027 
00028 typedef enum
00029 {
00030     IN_SESSION,
00031     NOT_IN_SESSION,
00032     QUICK_REFOCUS
00033 } SessionState;
00034 
00035 #define CHECK_RC(nRetVal, what)                                         \
00036   if (nRetVal != XN_STATUS_OK){                                         \
00037     printf ("%s failed: %s\n", what, xnGetStatusString (nRetVal));      \
00038     return nRetVal;                                                     \
00039   }
00040 
00041 SessionState g_SessionState = NOT_IN_SESSION;
00042 
00043 // Callback for when the focus is in progress
00044 void XN_CALLBACK_TYPE FocusProgress (const XnChar * strFocus, const XnPoint3D & ptPosition, XnFloat fProgress,
00045                                      void *UserCxt)
00046 {
00047     //printf("Focus progress: %s @(%f,%f,%f): %f\n", strFocus, ptPosition.X, ptPosition.Y, ptPosition.Z, fProgress);
00048 }
00049 
00050 // callback for session start
00051 void XN_CALLBACK_TYPE SessionStarting (const XnPoint3D & ptPosition, void *UserCxt)
00052 {
00053     printf ("Session start: (%f,%f,%f)\n", ptPosition.X, ptPosition.Y, ptPosition.Z);
00054     g_SessionState = IN_SESSION;
00055 }
00056 
00057 // Callback for session end
00058 void XN_CALLBACK_TYPE SessionEnding (void *UserCxt)
00059 {
00060     printf ("Session end\n");
00061     g_SessionState = NOT_IN_SESSION;
00062 }
00063 
00064 void XN_CALLBACK_TYPE NoHands (void *UserCxt)
00065 {
00066     printf ("Quick refocus\n");
00067     g_SessionState = QUICK_REFOCUS;
00068 }
00069 
00070 class XnVPointPublisher : public XnVPointControl
00071 {
00072 public:
00073     XnVPointPublisher(xn::DepthGenerator depthGenerator): XnVPointControl("XnVPointPublisher"), m_DepthGenerator(depthGenerator)
00074     {
00075     }
00076 
00077     virtual ~XnVPointPublisher()
00078     {
00079         std::map<XnUInt32, std::vector<XnPoint3D> >::iterator iter;
00080         for (iter = m_Position.begin(); iter != m_Position.end(); ++iter)
00081         {
00082             iter->second.clear();
00083         }
00084         m_Position.clear();
00085     }
00086 
00090     void OnPointCreate(const XnVHandPointContext* cxt)
00091     {
00092         printf("** %d\n", cxt->nID);
00093         m_Position[cxt->nID].resize(2);
00094         OnPointUpdate(cxt);
00095     }
00096 
00097     // Handle destruction of an existing hand
00098     void OnPointDestroy(XnUInt32 nID)
00099     {
00100         // No need for the history buffer
00101         m_Position.erase(nID);
00102     }
00106     void OnPointUpdate(const XnVHandPointContext* cxt)
00107     {
00108         // positions are kept in projective coordinates, since they are only used for drawing
00109         XnPoint3D ptPosition(cxt->ptPosition);
00110         XnPoint3D ptProjective(cxt->ptPosition);
00111         m_DepthGenerator.ConvertRealWorldToProjective(1, &ptProjective, &ptProjective);
00112         printf ("%d (%f,%f,%f) ", cxt->nID, cxt->ptPosition.X, cxt->ptPosition.Y, cxt->ptPosition.Z);
00113         printf (" -> (%f,%f,%f)\n", ptProjective.X, ptProjective.Y, ptProjective.Z);
00114 
00115         // Add new position to the history buffer
00116         m_Position[cxt->nID][0]=ptPosition;
00117         m_Position[cxt->nID][1]=ptProjective;
00118     }
00119 
00120 
00125     void Update(XnVMessage* pMessage) {
00126         // PointControl's Update calls all callbacks for each hand
00127         XnVPointControl::Update(pMessage);
00128 
00129         string frame_id("openni_depth_frame");
00130         string child_frame_id("hand_position");
00131 
00132         // get first hand
00133         if ( m_Position.size() > 0 ) {
00134             XnUInt32 Id = m_Position.begin()->first;
00135             XnPoint3D Position = m_Position.begin()->second[0];
00136             XnPoint3D Projection = m_Position.begin()->second[1];
00137 
00138             static tf::TransformBroadcaster br;
00139             tf::Transform transform;
00140             transform.setOrigin(tf::Vector3(Position.X/1000.0, Position.Y/1000.0, Position.Z/1000.0));
00141             transform.setRotation(tf::Quaternion(0,0,0,1));
00142             br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), frame_id, child_frame_id));
00143 
00144             geometry_msgs::PointStamped msg;
00145             msg.point.x = Projection.X;
00146             msg.point.y = Projection.Y;
00147             msg.header.stamp = ros::Time::now();
00148             hand_point_pub_.publish(msg);
00149         }
00150 
00151         std::map<XnUInt32, std::vector<XnPoint3D> >::const_iterator PointIterator;
00152         // Go over each existing hand
00153         for (PointIterator = m_Position.begin();
00154              PointIterator != m_Position.end();
00155              ++PointIterator)
00156         {
00157             XnUInt32 Id = PointIterator->first;
00158             string child_frame_id("hand_position");
00159             child_frame_id = child_frame_id + ((char)('0'+Id));
00160 
00161             // Go over all previous positions of current hand
00162             XnPoint3D Position = PointIterator->second[0];
00163             XnPoint3D Projection = PointIterator->second[1];
00164 
00165             static tf::TransformBroadcaster br;
00166             tf::Transform transform;
00167             transform.setOrigin(tf::Vector3(Position.X/1000.0, Position.Y/1000.0, Position.Z/1000.0));
00168             transform.setRotation(tf::Quaternion(0,0,0,1));
00169             br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), frame_id, child_frame_id));
00170         }
00171     }
00172 
00173 protected:
00174     // Source of the depth map
00175     xn::DepthGenerator m_DepthGenerator;
00176     // position per hand
00177     std::map<XnUInt32, std::vector<XnPoint3D> > m_Position;
00178 };
00179 
00180 // the publisher
00181 XnVPointPublisher* g_pPublisher;
00182 
00183 int main (int argc, char **argv)
00184 {
00185     ros::init (argc, argv, "openni_pointer");
00186     ros::NodeHandle nh;
00187 
00188     hand_point_pub_ = nh.advertise<geometry_msgs::PointStamped>("hand_position",10);
00189     hand_point_status_pub_ = nh.advertise<std_msgs::UInt8>("hand_position/status",10);
00190 
00191     // Initialize OpenNI
00192     string configFilename = ros::package::getPath ("openni_pointer") + "/openni_pointer.xml";
00193     XnStatus nRetVal = g_Context.InitFromXmlFile (configFilename.c_str ());
00194     CHECK_RC (nRetVal, "InitFromXml");
00195     nRetVal = g_Context.FindExistingNode (XN_NODE_TYPE_DEPTH, g_DepthGenerator);
00196     CHECK_RC (nRetVal, "Find depth generator");
00197     nRetVal = g_Context.FindExistingNode (XN_NODE_TYPE_HANDS, g_HandsGenerator);
00198     CHECK_RC (nRetVal, "Find hands generator");
00199 
00200     // Create Nite objects
00201     g_pSessionManager = new XnVSessionManager;
00202     nRetVal = g_pSessionManager->Initialize (&g_Context, "Click,Wave", "RaiseHand");
00203     CHECK_RC (nRetVal, "SessionManager::Initialize");
00204     g_pSessionManager->RegisterSession (NULL, SessionStarting, SessionEnding, FocusProgress);
00205 
00206     g_pPublisher = new XnVPointPublisher(g_DepthGenerator);
00207     g_pFlowRouter = new XnVFlowRouter;
00208     g_pFlowRouter->SetActive(g_pPublisher);
00209 
00210     //g_pFlowRouter->SetActive(g_pDrawer);
00211     g_pSessionManager->AddListener (g_pFlowRouter);
00212 
00213     g_pPublisher->RegisterNoPoints(NULL, NoHands);
00214 
00215     // Initialization done. Start generating
00216     nRetVal = g_Context.StartGeneratingAll ();
00217     CHECK_RC (nRetVal, "StartGenerating");
00218     ros::Rate r (30);
00219     while (ros::ok ())
00220     {
00221         g_Context.WaitAndUpdateAll ();
00222 
00223         // Update NITE tree
00224         g_pSessionManager->Update (&g_Context);
00225         switch (g_SessionState)
00226 
00227         {
00228         case IN_SESSION:
00229             ROS_INFO ("Tracking hands");
00230             break;
00231         case NOT_IN_SESSION:
00232             ROS_INFO ("Perform click or wave gestures to track hand");
00233             break;
00234         case QUICK_REFOCUS:
00235             ROS_INFO ("Raise your hand for it to be identified, or perform click or wave gestures");
00236             break;
00237         }
00238         std_msgs::UInt8 msg;
00239         msg.data = g_SessionState;
00240         hand_point_status_pub_.publish(msg);
00241 
00242         //publishTransforms();
00243         r.sleep ();
00244     }
00245     g_Context.Shutdown ();
00246     return 0;
00247 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines


openni_pointer
Author(s):
autogenerated on Sat Mar 23 2013 20:16:48