void runOnce (void)
  {
    xn::SceneMetaData sceneMD;
    xn::DepthMetaData depthMD_;

    // Read next available data
    // by Heresy, wait original depth generator
    g_Context.WaitOneUpdateAll( g_DepthGenerator );

    // Process the data
    g_DepthGenerator.GetMetaData (depthMD_);
    g_DepthGenerator.GetMetaData (depthMD);
    depthMD_.MakeDataWritable();
    xn::DepthMap& depthMap_ = depthMD_.WritableDepthMap();
    xn::DepthMap& depthMap = depthMD.WritableDepthMap();

    static float *buffer = 0;
    if (buffer == 0)
    {
      std::cout << "(re)allocating depth buffer" << std::endl;
      buffer = (float*) malloc (depthMap.XRes() * depthMap.YRes() * sizeof(float));
    }
    for (XnUInt y = 0; y < depthMap.YRes(); y++)
    {
      for (XnUInt x = 0; x < depthMap.XRes(); x++)
      {
        buffer [x + y * depthMap.XRes()] = depthMap (depthMap.XRes() - x - 1, y) * 0.001;
      }
    }

    float P[12];
    P[0] = 585.260; P[1] = 0.0;     P[2]  = 317.387; P[3]  = 0.0;
    P[4] = 0.0;     P[5] = 585.028; P[6]  = 239.264; P[7]  = 0.0;
    P[8] = 0.0;     P[9] = 0.0;     P[10] = 1.0;     P[11] = 0.0;
  
    double fx = P[0];
    double fy = P[5];
    double cx = P[2];
    double cy = P[6];
    double far_plane_ = 8;
    double near_plane_ = 0.1;
  
    double glTf[16];
    for (unsigned int i = 0; i < 16; ++i)
      glTf[i] = 0.0;

    // calculate the projection matrix
    // NOTE: this minus is there to flip the x-axis of the image.
    glTf[0]= -2.0 * fx / depthMap.XRes();
    glTf[5]= 2.0 * fy / depthMap.YRes();

    glTf[8]= 2.0 * (0.5 - cx / depthMap.XRes());
    glTf[9]= 2.0 * (cy / depthMap.YRes() - 0.5);

    glTf[10]= - (far_plane_ + near_plane_) / (far_plane_ - near_plane_);
    glTf[14]= -2.0 * far_plane_ * near_plane_ / (far_plane_ - near_plane_);

    glTf[11]= -1;


    filter->filter ((unsigned char*)buffer, glTf, depthMap.XRes(), depthMap.YRes());

    GLfloat* masked_depth = filter->getMaskedDepth();

    for (XnUInt y = 0; y < depthMap.YRes(); y++)
    {
      for (XnUInt x = 0; x < depthMap.XRes(); x++)
      {
          depthMap_(x, y) = XnDepthPixel (masked_depth[x + y * depthMap.XRes()] * 1000); 
      }
    }

    mockDepth.SetData(depthMD_);

	publishTransforms (std::string("openni_depth_frame"));
  }
int main(int argc, char **argv){
  ros::init(argc, argv, "pplTracker");
  ros::NodeHandle nh;

  std::string configFilename = ros::package::getPath("people_tracker_denbyk") + "/init/openni_tracker.xml";
  genericUserCalibrationFileName = ros::package::getPath("people_tracker_denbyk") + "/init/GenericUserCalibration.bin";

  ros::Rate loop_rate(1);

  //valore di ritorno Xn
  XnStatus nRetVal;

  //while (ros::ok())
  while (nh.ok())
  {
    //inizializzo contesto openni
    //ROS_INFO(configFilename.c_str(),xnGetStatusString(nRetVal));
    nRetVal = g_Context.InitFromXmlFile(configFilename.c_str());

    //TODO: remove
    nRetVal = XN_STATUS_OK;

    //riprovo tra un po'
    if(nRetVal != XN_STATUS_OK)
    {
      ROS_INFO("InitFromXml failed: %s Retrying in 3 seconds...", xnGetStatusString(nRetVal));
      ros::Duration(3).sleep();

    }
    else
    {
      break;
    }
  }


  //std::string frame_id;

  nRetVal = g_Context.FindExistingNode(XN_NODE_TYPE_DEPTH, g_DepthGenerator);


  if(nRetVal != XN_STATUS_OK)
  {
    ROS_ERROR("Find depth generator failed: %s", xnGetStatusString(nRetVal));
  }

  //cerca nodo ti tipo user generator e lo salva in g_UserGenerator
  nRetVal = g_Context.FindExistingNode(XN_NODE_TYPE_USER, g_UserGenerator);


  if (nRetVal != XN_STATUS_OK)
  {
    //crea lo userGenerator del g_context. SE non riesce probabilmente manca NITE
    nRetVal = g_UserGenerator.Create(g_Context);

    if (nRetVal != XN_STATUS_OK)
    {
      ROS_ERROR("NITE is likely missing: Please install NITE >= 1.5.2.21. Check the readme for download information. Error Info: User generator failed: %s", xnGetStatusString(nRetVal));
      return nRetVal;
    }
  }
  //veriica che lo userGenerator creato supporti SKELETON
  if (!g_UserGenerator.IsCapabilitySupported(XN_CAPABILITY_SKELETON))
  {
    ROS_INFO("Supplied user generator doesn't support skeleton");
    return EXIT_FAILURE;
  }

  //imposto la modalità dello skeleton, quali giunzioni rilevare e quali no.
  //in questo caso upper è il torso/la testa
  g_UserGenerator.GetSkeletonCap().SetSkeletonProfile(XN_SKEL_PROFILE_UPPER);

  //setto varie callbacks per entrata, uscita e rientro user nello UserGenerator
  XnCallbackHandle hUserCallbacks;
  g_UserGenerator.RegisterUserCallbacks(User_NewUser, User_LostUser, NULL, hUserCallbacks);
  g_UserGenerator.RegisterToUserExit(User_OutOfScene, NULL, hUserCallbacks);
  g_UserGenerator.RegisterToUserReEnter(User_BackIntoScene, NULL, hUserCallbacks);

  //attivo la generazione dei vari generators
  nRetVal = g_Context.StartGeneratingAll();

  if(nRetVal != XN_STATUS_OK)
  {
    ROS_ERROR("StartGenerating failed: %s", xnGetStatusString(nRetVal));
  }

  //recupera un parametro passato al nodo dal server dei parametri ROS.
  //usando la chiave camera_frame_id e lo memorizza nella variabile frame_id
  std::string frame_id("camera_depth_frame");
  nh.getParam("camera_frame_id", frame_id);


  std::cout << "init ok\n";
  //ciclo principale.
  while(nh.ok())
  {
    //aggiorna il contesto e aspetta
    g_Context.WaitAndUpdateAll();
    //pubblica le trasformazioni su frame_id
    publishTransforms(frame_id);
    //dormi per un tot.
    ros::Rate(30).sleep();
  }

  //rilascia risorse e esci.
  g_Context.Shutdown();
  return EXIT_SUCCESS;
}