Revision: 9052
          http://playerstage.svn.sourceforge.net/playerstage/?rev=9052&view=rev
Author:   jpgr87
Date:     2011-05-24 04:53:42 +0000 (Tue, 24 May 2011)

Log Message:
-----------
New driver: kinect

Modified Paths:
--------------
    code/player/trunk/client_libs/libplayerc/playerc.h
    code/player/trunk/server/drivers/camera/CMakeLists.txt

Added Paths:
-----------
    code/player/trunk/config/kinect.cfg
    code/player/trunk/server/drivers/camera/kinect/
    code/player/trunk/server/drivers/camera/kinect/CMakeLists.txt
    code/player/trunk/server/drivers/camera/kinect/kinectdriver.cc

Modified: code/player/trunk/client_libs/libplayerc/playerc.h
===================================================================
--- code/player/trunk/client_libs/libplayerc/playerc.h  2011-05-24 02:17:51 UTC 
(rev 9051)
+++ code/player/trunk/client_libs/libplayerc/playerc.h  2011-05-24 04:53:42 UTC 
(rev 9052)
@@ -1616,7 +1616,9 @@
 /**************************************************************************/
 
 /***************************************************************************/
-/** @defgroup playerc_proxy_gps gps
+/** @ingroup playerc_proxies
+ * @defgroup playerc_proxy_gps gps
+ *
 
 The gps proxy provides an interface to a GPS-receiver.
 

Added: code/player/trunk/config/kinect.cfg
===================================================================
--- code/player/trunk/config/kinect.cfg                         (rev 0)
+++ code/player/trunk/config/kinect.cfg 2011-05-24 04:53:42 UTC (rev 9052)
@@ -0,0 +1,12 @@
+# Example configuration for Kinect driver
+# Rich Mattes
+driver
+(
+  name "kinect"
+  plugin "kinectdriver.so"
+#  provides ["image:::camera:0" "depth:::camera:1"]  
+  provides ["image:::camera:0" "depth:::camera:1" "ptz:0" "imu:0"]
+  heatmap 0
+  downsample 0
+  alwayson 1
+)

Modified: code/player/trunk/server/drivers/camera/CMakeLists.txt
===================================================================
--- code/player/trunk/server/drivers/camera/CMakeLists.txt      2011-05-24 
02:17:51 UTC (rev 9051)
+++ code/player/trunk/server/drivers/camera/CMakeLists.txt      2011-05-24 
04:53:42 UTC (rev 9052)
@@ -9,6 +9,7 @@
 ADD_SUBDIRECTORY (imageseq)
 ADD_SUBDIRECTORY (imgcmp)
 ADD_SUBDIRECTORY (imgsave)
+ADD_SUBDIRECTORY (kinect)
 ADD_SUBDIRECTORY (powershot)
 ADD_SUBDIRECTORY (sphere)
 ADD_SUBDIRECTORY (uvc)

Added: code/player/trunk/server/drivers/camera/kinect/CMakeLists.txt
===================================================================
--- code/player/trunk/server/drivers/camera/kinect/CMakeLists.txt               
                (rev 0)
+++ code/player/trunk/server/drivers/camera/kinect/CMakeLists.txt       
2011-05-24 04:53:42 UTC (rev 9052)
@@ -0,0 +1,14 @@
+PLAYERDRIVER_OPTION (kinect build_kinect ON)
+
+PLAYERDRIVER_REQUIRE_PKG (kinect build_kinect libfreenect freenect_includeDirs
+    freenect_libDirs freenect_linkLibs freenect_linkFlags freenect_cFlags)
+PLAYERDRIVER_REQUIRE_PKG (kinect build_kinect libusb-1.0 libusb_includeDirs
+    libusb_libDirs libusb_linkLibs libusb_linkFlags libusb_cFlags)
+
+PLAYERDRIVER_ADD_DRIVER (kinect build_kinect
+                         INCLUDEDIRS ${freenect_includeDirs} 
+                         LIBDIRS ${freenect_libDirs} 
+                         LINKLIBS ${freenect_linkLibs} ${libusb_linkLibs}
+                         LINKFLAGS ${freenect_linkFlags} 
+                         CFLAGS ${freenect_cFlags} ${libusb_cFlags}
+                         SOURCES kinectdriver.cc)

Added: code/player/trunk/server/drivers/camera/kinect/kinectdriver.cc
===================================================================
--- code/player/trunk/server/drivers/camera/kinect/kinectdriver.cc              
                (rev 0)
+++ code/player/trunk/server/drivers/camera/kinect/kinectdriver.cc      
2011-05-24 04:53:42 UTC (rev 9052)
@@ -0,0 +1,696 @@
+/*
+ *  Kinect Driver for Player
+ *  Copyright (C) 2011
+ *     Rich Mattes
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/** @ingroup drivers */
+/** @{ */
+/** @defgroup driver_kinect kinect
+ * @brief USB camera driver for Microsoft Kinect camera
+
+Device driver for Microsoft Kinect webcams.  This driver handles processing
+the RGB Color images and the greyscale depth images provided by the Kinect,
+as well as motor control for PTZ, and reading the accelerometer.  The Kinect
+also supports audio and LED control, these capabilities are under development.
+
+This driver is based on the latest version of the libfreenect API, which
+is currently under heavy development.
+
+Heatmap code and USB connection code based on "glview" example in libfreenect
+project.
+
+@par Compile-time dependencies
+
+- libfreenect - http://github.com/OpenKinect/libfreenect
+- libusb-1.0 - http://www.libusb.org/wiki/libusb-1.0
+
+@par Requires
+
+- none
+
+@par Provides
+
+- @ref interface_camera - Color image (mandatory)
+- @ref interface_camera - Depth image (optional)
+- @ref interface_ptz - Tilt motor
+- @ref interface_imu - Accelerometer
+
+@par Configuration requests
+
+- None
+
+@par Configuration file options
+
+- heatmap (bool)
+  - Default: false
+  - When set to false, the Depth image is published as a greyscale image
+  - When set to true, the Depth image is colorized and published as an RGB 
heatmap
+
+- downsample (bool)
+  - Default: false
+  - When set to false, the Depth image is published as a greyscale MONO16 image
+  - When set to true, the Depth image is downsampled into a greyscale MONO8 
image
+  - If heatmap is set to true, this option has no effect.
+
+- color_resolution (enumeration)
+  - Default: 2
+  - Corresponds to the resolution of the color image frame.
+  - 2 = High Resolution = 1280x1024
+  - 1 = Med Resolution = 640x480
+
+- depth_resolution (enumeration)
+  - Default: 1
+  - Corresponds to the resolution of the depth image frame
+  - 1 = Med resolution = 640x488
+  - 0 = Low Resolution = 320x240
+
+@par Example
+
+@verbatim
+driver
+(
+  name "kinect"
+  provides ["color:::camera:0" "depth:::camera:1" "ptz:0" "imu:0"]
+  heatmap 0
+  downsample 1
+  color_resolution 2
+  depth_resolution 1
+)
+@endverbatim
+
+@authors Rich Mattes
+ */
+/** @} */
+
+//TODO: Add support for LEDs, pointcloud, user-defined image sizes
+//TODO: Less judicious use of memcpy
+
+#if !defined (WIN32)
+#include <unistd.h>
+#endif
+#include <string.h>
+#include <cmath>
+
+#include <libplayercore/playercore.h>
+#include <libusb-1.0/libusb.h>
+#include <libfreenect/libfreenect.h>
+
+
+// Callback functions for processing depth and color image buffers
+void DepthImageCallback(freenect_device *dev, void *depth, uint32_t timestamp);
+void ColorImageCallback(freenect_device *dev, void *rgb, uint32_t timestamp);
+
+// Storage for image data and metadata
+static uint16_t* DepthImage;
+static uint8_t* ColorImage;
+static pthread_mutex_t kinect_mutex;
+static int newcdata, newddata;
+static freenect_frame_mode colorImageMode;
+static freenect_frame_mode depthImageMode;
+
+const bool DEFAULT_HEATMAP = false;
+const bool DEFAULT_DOWNSAMPLE = false;
+const int DEFAULT_COLOR_RESOLUTION = FREENECT_RESOLUTION_HIGH;
+const int DEFAULT_DEPTH_RESOLUTION = FREENECT_RESOLUTION_MEDIUM;
+
+////////////////////////////////////////////////////////////////////////////////
+// The class for the driver
+class KinectDriver : public ThreadedDriver
+{
+public:
+
+       // Constructor; need that
+       KinectDriver(ConfigFile* cf, int section);
+
+       // This method will be invoked on each incoming message
+       virtual int ProcessMessage(QueuePointer &resp_queue,
+                       player_msghdr * hdr,
+                       void * data);
+
+private:
+
+       // Main function for device thread.
+       virtual void Main();
+       virtual int MainSetup();
+       virtual void MainQuit();
+
+       // Routines to publish different data
+       int PublishColorImage();
+       int PublishDepthImage();
+       int PublishPTZ();
+       int PublishAccelerometer();
+
+       // Handles for libfreenect
+       freenect_context *fctx;
+       freenect_device *fdev;
+
+       // Device addresses for all possible provided interfaces
+       player_devaddr_t color_camera_id;
+       player_devaddr_t depth_camera_id;
+       player_devaddr_t ptz_id;
+       player_devaddr_t imu_id;
+
+       // Storage for outgoing interface data
+       player_camera_data_t colordata;
+       player_camera_data_t depthdata;
+       player_ptz_data_t ptzdata;
+       player_imu_data_calib_t imudata;
+
+       // Flags for interfaces we provide
+       int providedepthimage;
+       int provideptz;
+       int provideimu;
+
+       // Timers for publishing ptz and accelerometers regularly
+       double last_acc_pub;
+       double last_ptz_pub;
+
+       // Config file options
+       BoolProperty heatmap;
+       BoolProperty downsample;
+       IntProperty color_resolution;
+       IntProperty depth_resolution;
+
+       // Lookup table for depth image colorization
+       uint16_t t_gamma[2048];
+};
+
+
+// Startup instance of the driver
+Driver* KinectDriver_Init(ConfigFile* cf, int section)
+{
+       // Create and return a new instance of this driver
+       return((Driver*)(new KinectDriver(cf, section)));
+}
+
+// Register driver with server
+void kinect_Register(DriverTable* table)
+{
+       table->AddDriver("kinect", KinectDriver_Init);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Constructor.  Retrieve options from the configuration file and do any
+// pre-Setup() setup.
+KinectDriver::KinectDriver(ConfigFile* cf, int section)
+: ThreadedDriver(cf, section),
+  heatmap("heatmap", DEFAULT_HEATMAP, false),
+  downsample("downsample", DEFAULT_DOWNSAMPLE, false),
+  color_resolution("color_resolution", DEFAULT_COLOR_RESOLUTION, false),
+  depth_resolution("depth_resolution", DEFAULT_DEPTH_RESOLUTION, false)
+{
+       // Initialize flags:
+       providedepthimage = 0;
+       provideptz = 0;
+       provideimu = 0;
+
+       //Add interface from Configuration File
+       if (cf->ReadDeviceAddr(&(this->color_camera_id), section, "provides", 
PLAYER_CAMERA_CODE, -1, "image"))
+       {
+               PLAYER_ERROR("Kinect's Camera interface not started: config 
file doesn't provide \"image:::camera:n\"");
+               this->SetError(-1);
+               return;
+       }
+       if (this->AddInterface(this->color_camera_id))
+       {
+               PLAYER_ERROR("Kinect's Camera interface failed to be added.");
+               this->SetError(-1);
+               return;
+       }
+       if (cf->ReadDeviceAddr(&(this->depth_camera_id), section, "provides", 
PLAYER_CAMERA_CODE, -1, "depth"))
+       {
+               PLAYER_WARN("Kinect's Depth interface not started: config file 
doesn't provide \"depth:::camera:n\"");
+       }
+       else
+       {
+               if (this->AddInterface(this->depth_camera_id))
+               {
+                       PLAYER_ERROR("Kinect's Depth Camera interface failed to 
be added.");
+                       this->SetError(-1);
+                       return;
+               }
+               providedepthimage = 1;
+       }
+
+       // Check to see if we provide the PTZ interface
+       if (cf->ReadDeviceAddr(&(this->ptz_id), section, "provides", 
PLAYER_PTZ_CODE, -1, NULL))
+       {
+               PLAYER_WARN("Kinect driver not providing PTZ.");
+       }
+       else{
+               if (this->AddInterface(this->ptz_id))
+               {
+                       PLAYER_ERROR("Kinect's PTZ interface failed to be 
added.");
+                       this->SetError(-1);
+                       return;
+               }
+               provideptz = 1;
+       }
+
+       // Check to see if we provide the IMU interface
+       if (cf->ReadDeviceAddr(&(this->imu_id), section, "provides", 
PLAYER_IMU_CODE, -1, NULL))
+       {
+               PLAYER_WARN("Kinect driver not providing IMU.");
+       }
+       else{
+               if (this->AddInterface(this->imu_id))
+               {
+                       PLAYER_ERROR("Kinect's IMU interface failed to be 
added.");
+                       this->SetError(-1);
+                       return;
+               }
+               provideimu = 1;
+       }
+
+       // Read config file options
+       RegisterProperty("heatmap", &this->heatmap, cf, section);
+       RegisterProperty("downsample", &this->downsample, cf, section);
+       RegisterProperty("color_resolution", &this->color_resolution, cf, 
section);
+       RegisterProperty("depth_resolution", &this->depth_resolution, cf, 
section);
+
+
+       // Initialize the color map lookup table
+       for (int i=0; i<2048; i++) {
+                       float v = i/2048.0;
+                       v = powf(v, 3)* 6;
+                       t_gamma[i] = v*6*256;
+               }
+
+       return;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Set up the device.  Return 0 if things go well, and -1 otherwise.
+int KinectDriver::MainSetup()
+{
+       PLAYER_MSG0(1,"Kinect driver initializing...");
+       kinect_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+       if (freenect_init(&fctx, NULL) < 0)
+       {
+               PLAYER_ERROR("Error initializing Kinect");
+               return -1;
+       }
+       if (freenect_open_device(fctx, &fdev, 0) < 0)
+       {
+               PLAYER_ERROR("Error opening Kinect");
+               return -1;
+       }
+       //Presto reduced the update size by 80% (from 305 M to 62 M).
+
+
+       freenect_set_depth_callback(fdev, DepthImageCallback);
+       freenect_set_video_callback(fdev, ColorImageCallback);
+       colorImageMode = 
freenect_find_video_mode((freenect_resolution)color_resolution.GetValue(), 
FREENECT_VIDEO_RGB);
+       freenect_set_video_mode(fdev, colorImageMode);
+       depthImageMode = 
freenect_find_depth_mode((freenect_resolution)depth_resolution.GetValue(), 
FREENECT_DEPTH_11BIT);
+       freenect_set_depth_mode(fdev, depthImageMode);
+
+       colordata.image = NULL;
+       depthdata.image = NULL;
+
+       freenect_start_depth(fdev);
+       freenect_start_video(fdev);
+
+       last_acc_pub = 0;
+       last_ptz_pub = 0;
+
+       return(0);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Shutdown the device
+void KinectDriver::MainQuit()
+{
+       PLAYER_MSG0(2,"Kinect driver shutting down...");
+
+       freenect_stop_depth(fdev);
+       freenect_stop_video(fdev);
+       freenect_shutdown(fctx);
+
+       PLAYER_MSG0(2,"Kinect driver has been shut down.");
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Message handling function
+int KinectDriver::ProcessMessage(QueuePointer & resp_queue,
+               player_msghdr * hdr,
+               void * data)
+{
+       // Respond to this so clients know that a NACK for every other request 
is intended
+       HANDLE_CAPABILITY_REQUEST (device_addr, resp_queue, hdr, data, 
PLAYER_MSGTYPE_REQ, PLAYER_CAPABILITIES_REQ);
+
+       if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, 
PLAYER_SET_INTPROP_REQ, this->color_camera_id))
+       {
+               player_intprop_req_t *propreq = 
reinterpret_cast<player_intprop_req_t*>(data);
+               if (!strncmp(propreq->key, "color_resolution", 17))
+               {
+                       int newres = propreq->value;
+                       if (newres > FREENECT_RESOLUTION_HIGH || newres < 
FREENECT_RESOLUTION_LOW)
+                       {
+                               // Desired value is out of range, warn the user 
and ignore the request
+                               PLAYER_WARN1("Property value %d for 
\"color_resolution\" is out of range, ignoring...", newres);
+                               return -1;
+                       }
+                       else if(newres == colorImageMode.resolution)
+                       {
+                               // Already at this resolution, don't do 
anything and indicate that everything is fine
+                               Publish(hdr->addr, resp_queue, 
PLAYER_MSGTYPE_RESP_ACK, PLAYER_SET_INTPROP_REQ, NULL, 0, NULL);
+                               return 0;
+                       }
+                       else
+                       {
+                               PLAYER_WARN1("Setting color image resolution to 
%d", newres);
+                               // Have a different resolution, do something 
about it.
+                               freenect_stop_video(fdev);
+                               pthread_mutex_lock(&kinect_mutex);
+                               colorImageMode = 
freenect_find_video_mode((freenect_resolution)newres, FREENECT_VIDEO_RGB);
+                               freenect_set_video_mode(fdev, colorImageMode);
+                               pthread_mutex_unlock(&kinect_mutex);
+                               freenect_start_video(fdev);
+                               Publish(hdr->addr, resp_queue, 
PLAYER_MSGTYPE_RESP_ACK, PLAYER_SET_INTPROP_REQ, NULL, 0, NULL);
+                               return 0;
+                       }
+               }
+       }
+
+       if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, 
PLAYER_SET_INTPROP_REQ, this->depth_camera_id))
+               {
+                       player_intprop_req_t *propreq = 
reinterpret_cast<player_intprop_req_t*>(data);
+                       if (!strncmp(propreq->key, "depth_resolution", 17))
+                       {
+                               int newres = propreq->value;
+                               if (newres > FREENECT_RESOLUTION_MEDIUM || 
newres < FREENECT_RESOLUTION_LOW)
+                               {
+                                       // Desired value is out of range, warn 
the user and ignore the request
+                                       PLAYER_WARN1("Property value %d for 
\"depth_resolution\" is out of range, ignoring...", newres);
+                                       return -1;
+                               }
+                               else if(newres == depthImageMode.resolution)
+                               {
+                                       // Already at this resolution, don't do 
anything and indicate that everything is fine
+                                       Publish(hdr->addr, resp_queue, 
PLAYER_MSGTYPE_RESP_ACK, PLAYER_SET_INTPROP_REQ, NULL, 0, NULL);
+                                       return 0;
+                               }
+                               else
+                               {
+                                       // Have a different resolution, do 
something about it.
+                                       freenect_stop_depth(fdev);
+                                       pthread_mutex_lock(&kinect_mutex);
+                                       colorImageMode = 
freenect_find_depth_mode((freenect_resolution)newres, FREENECT_DEPTH_11BIT);
+                                       freenect_set_depth_mode(fdev, 
depthImageMode);
+                                       pthread_mutex_unlock(&kinect_mutex);
+                                       freenect_start_depth(fdev);
+                                       Publish(hdr->addr, resp_queue, 
PLAYER_MSGTYPE_RESP_ACK, PLAYER_SET_INTPROP_REQ, NULL, 0, NULL);
+                                       return 0;
+                               }
+                       }
+               }
+
+       if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_CMD, 
PLAYER_PTZ_CMD_STATE, this->ptz_id))
+       {
+               player_ptz_cmd_t *ptzcmd = (player_ptz_cmd_t*) data;
+               int tiltcmd = round(ptzcmd->tilt * 180.0 / M_PI);
+
+               if (tiltcmd < -30)
+               {
+                       PLAYER_WARN1("Kinect tilt command (%d deg) out of 
range, limiting to (-30 deg)", tiltcmd);
+                       tiltcmd = -30;
+               }
+               else if (tiltcmd > 30)
+               {
+                       PLAYER_WARN1("Kinect tilt command (%d deg) out of 
range, limiting to (+30 deg)", tiltcmd);
+                       tiltcmd = 30;
+               }
+
+               // Only do something if the last command is different from the 
current one
+               if (tiltcmd != round(this->ptzdata.tilt * 180.0 / M_PI))
+               {
+                       freenect_set_tilt_degs(fdev, (double)tiltcmd);
+                       this->ptzdata.tilt = ptzcmd->tilt;
+               }
+               return 0;
+       }
+
+       // Don't understand the message, return with an error
+       return(-1);
+}
+////////////////////////////////////////////////////////////////////////////////
+// Publish color image data to camera interface
+int KinectDriver::PublishColorImage()
+{
+       if (colordata.image){
+               delete[] colordata.image;
+       }
+       colordata.image = new uint8_t[colorImageMode.bytes];
+
+       pthread_mutex_lock(&kinect_mutex);
+       colordata.width = colorImageMode.width;
+       colordata.height = colorImageMode.height;
+       memcpy(colordata.image, ColorImage, colorImageMode.bytes);
+       pthread_mutex_unlock(&kinect_mutex);
+
+       colordata.bpp = 24;
+       colordata.compression = PLAYER_CAMERA_COMPRESS_RAW;
+       colordata.fdiv = 1;
+       colordata.image_count = colorImageMode.bytes;
+       colordata.format = PLAYER_CAMERA_FORMAT_RGB888;
+
+       PLAYER_MSG2(4,"Writing Color Image size %d, %d", colordata.width, 
colordata.height);
+       Publish(color_camera_id, PLAYER_MSGTYPE_DATA, PLAYER_CAMERA_DATA_STATE, 
(void*)&colordata);
+       newcdata = 0;
+
+       return 0;
+
+}
+////////////////////////////////////////////////////////////////////////////////
+// Publish depth image data to camera interface
+int KinectDriver::PublishDepthImage()
+{
+
+       if (depthdata.image){
+               delete[] depthdata.image;
+       }
+       // Allocate space for maximum possible display image size (RGB888 with 
depth image's wxh)
+       depthdata.image = new uint8_t[depthImageMode.width * 
depthImageMode.height * 3];
+
+       if (heatmap) // Publish colorized RGB888
+       {
+               pthread_mutex_lock(&kinect_mutex);
+               depthdata.width = depthImageMode.width;
+               depthdata.height = depthImageMode.height;
+               for (unsigned int i=0; i<depthdata.width*depthdata.height; i++) 
{
+                       int pval = t_gamma[DepthImage[i]];
+                       int lb = pval & 0xff;
+                       switch (pval>>8) {
+                       case 0:
+                               depthdata.image[3*i+0] = 255;
+                               depthdata.image[3*i+1] = 255-lb;
+                               depthdata.image[3*i+2] = 255-lb;
+                               break;
+                       case 1:
+                               depthdata.image[3*i+0] = 255;
+                               depthdata.image[3*i+1] = lb;
+                               depthdata.image[3*i+2] = 0;
+                               break;
+                       case 2:
+                               depthdata.image[3*i+0] = 255-lb;
+                               depthdata.image[3*i+1] = 255;
+                               depthdata.image[3*i+2] = 0;
+                               break;
+                       case 3:
+                               depthdata.image[3*i+0] = 0;
+                               depthdata.image[3*i+1] = 255;
+                               depthdata.image[3*i+2] = lb;
+                               break;
+                       case 4:
+                               depthdata.image[3*i+0] = 0;
+                               depthdata.image[3*i+1] = 255-lb;
+                               depthdata.image[3*i+2] = 255;
+                               break;
+                       case 5:
+                               depthdata.image[3*i+0] = 0;
+                               depthdata.image[3*i+1] = 0;
+                               depthdata.image[3*i+2] = 255-lb;
+                               break;
+                       default:
+                               depthdata.image[3*i+0] = 0;
+                               depthdata.image[3*i+1] = 0;
+                               depthdata.image[3*i+2] = 0;
+                               break;
+                       }
+               }
+               pthread_mutex_unlock(&kinect_mutex);
+
+               depthdata.bpp = 24;
+               depthdata.compression = PLAYER_CAMERA_COMPRESS_RAW;
+               depthdata.fdiv = 1;
+               depthdata.image_count = depthdata.width*depthdata.height*3;
+               depthdata.format = PLAYER_CAMERA_FORMAT_RGB888;
+       }
+       else if (downsample) //Publish downsampled MONO8
+       {
+               pthread_mutex_lock(&kinect_mutex);
+               depthdata.width = depthImageMode.width;
+               depthdata.height = depthImageMode.height;
+               for (unsigned int i=0; i < depthdata.width* depthdata.height; 
i++)
+               {
+                       uint16_t pixel = DepthImage[i];
+                       uint8_t dpixel = (uint8_t)((double)pixel / 2048.0 * 
255.0); 
+                       depthdata.image[i] = dpixel;
+               }
+               pthread_mutex_unlock(&kinect_mutex);
+
+               depthdata.bpp = 8;
+               depthdata.compression = PLAYER_CAMERA_COMPRESS_RAW;
+               depthdata.fdiv = 1;
+               depthdata.image_count = depthImageMode.width * 
depthImageMode.height;
+               depthdata.format = PLAYER_CAMERA_FORMAT_MONO8;
+       }
+       else // Publish MONO16  
+       {
+               pthread_mutex_lock(&kinect_mutex);
+               depthdata.width = depthImageMode.width;
+               depthdata.height = depthImageMode.height;
+               memcpy((void*)depthdata.image, (void*)DepthImage, 
depthImageMode.bytes);
+               pthread_mutex_unlock(&kinect_mutex);
+
+
+               depthdata.bpp = 16;
+               depthdata.compression = PLAYER_CAMERA_COMPRESS_RAW;
+               depthdata.fdiv = 1;
+               depthdata.image_count = depthImageMode.bytes;
+               depthdata.format = PLAYER_CAMERA_FORMAT_MONO16;
+       }
+
+       PLAYER_MSG2(4,"Writing Depth Image size %d, %d", depthdata.width, 
depthdata.height);
+       newddata = 0;
+       Publish(depth_camera_id, PLAYER_MSGTYPE_DATA, PLAYER_CAMERA_DATA_STATE, 
(void*)&depthdata);
+
+       return 0;
+}
+int KinectDriver::PublishPTZ()
+{
+       Publish(this->ptz_id, PLAYER_MSGTYPE_DATA, PLAYER_PTZ_DATA_STATE, 
(void*)&ptzdata, sizeof(ptzdata));
+       return 0;
+}
+
+int KinectDriver::PublishAccelerometer()
+{
+       if (freenect_update_tilt_state(fdev))
+       {
+               double x, y, z;
+               freenect_raw_tilt_state *rawstate = 
freenect_get_tilt_state(fdev);
+               if( rawstate )
+               {
+                       freenect_get_mks_accel(rawstate, &x, &y, &z);
+                       imudata.accel_x = x;
+                       imudata.accel_y = y;
+                       imudata.accel_z = z;
+
+                       Publish(this->imu_id, PLAYER_MSGTYPE_DATA, 
PLAYER_IMU_DATA_CALIB, (void*)&imudata, sizeof(imudata));
+                       return 0;
+               }
+       }
+       // Didn't get to return 0
+       PLAYER_WARN("Error retrieving accelerometer data.");
+       return -1;
+}
+////////////////////////////////////////////////////////////////////////////////
+// Main function for device thread
+void KinectDriver::Main()
+{
+       // The main loop; interact with the device here
+       for(;;)
+       {
+               // test if we are supposed to cancel
+               pthread_testcancel();
+
+               // Cycle libusb
+               freenect_process_events(fctx);
+
+               // Process incoming messages.  KinectDriver::ProcessMessage() is
+               // called on each message.
+               ProcessMessages();
+
+               // Check each camera to see if there's new data available
+               // from the callbacks.  If so, publish it.
+               if (newcdata)
+               {
+                       PublishColorImage();
+               }
+               if (providedepthimage && newddata)
+               {
+                       PublishDepthImage();
+               }
+
+               double now;
+               GlobalTime->GetTimeDouble(&now);
+               // If this happens on every iteration, the image frames
+               // don't get through.  Limit it to updating 20ish times a second
+               if (provideimu && (now - last_acc_pub) > .05)
+               {
+                       PublishAccelerometer();
+                       last_acc_pub = now;
+               }
+               // PTZ state data isn't terribly important, publish every
+               // half second or so.
+               if (provideptz && (now - last_ptz_pub) > 0.5)
+               {
+                       PublishPTZ();
+                       last_ptz_pub = now;
+               }
+
+               // Sleep so we don't kill the processor
+               usleep(10);
+       }
+}
+////////////////////////////////////////////////////////////////////////////////
+// Grab depth image buffer returned by libfreenect and store it in a static 
buffer
+void DepthImageCallback(freenect_device *dev, void *imagedata, uint32_t 
timestamp)
+{
+       pthread_mutex_lock(&kinect_mutex);
+       if(DepthImage)
+       {
+               delete[] DepthImage;
+       }
+
+       DepthImage = new uint16_t[depthImageMode.bytes];
+       memcpy(DepthImage, imagedata, depthImageMode.bytes);
+       newddata = 1;
+       pthread_mutex_unlock(&kinect_mutex);
+       return;
+}
+////////////////////////////////////////////////////////////////////////////////
+// Grab color image buffer returned by libfreenect and store it in a static 
buffer
+void ColorImageCallback(freenect_device *dev, void *imagedata, uint32_t 
timestamp)
+{
+       pthread_mutex_lock(&kinect_mutex);
+       if(ColorImage)
+       {
+               delete[] ColorImage;
+       }
+       ColorImage = new uint8_t[colorImageMode.bytes];
+       memcpy(ColorImage, imagedata, colorImageMode.bytes);
+       newcdata = 1;
+       pthread_mutex_unlock(&kinect_mutex);
+       return;
+}
+


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

------------------------------------------------------------------------------
vRanger cuts backup time in half-while increasing security.
With the market-leading solution for virtual backup and recovery, 
you get blazing-fast, flexible, and affordable data protection.
Download your free trial now. 
http://p.sf.net/sfu/quest-d2dcopy1
_______________________________________________
Playerstage-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/playerstage-commit

Reply via email to