Created
October 20, 2012 09:17
-
-
Save trtg/3922745 to your computer and use it in GitHub Desktop.
Using NITE for kinect to control the mouse cursor under X11 in linux
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/**************************************************************************** | |
* * | |
* Nite 1.3 - Single Control Sample * | |
* * | |
* Author: Oz Magal * | |
* * | |
****************************************************************************/ | |
/**************************************************************************** | |
* * | |
* Nite 1.3 * | |
* Copyright (C) 2006 PrimeSense Ltd. All Rights Reserved. * | |
* * | |
* This file has been provided pursuant to a License Agreement containing * | |
* restrictions on its use. This data contains valuable trade secrets * | |
* and proprietary information of PrimeSense Ltd. and is protected by law. * | |
* * | |
****************************************************************************/ | |
//----------------------------------------------------------------------------- | |
// Headers | |
//----------------------------------------------------------------------------- | |
// General headers | |
#include <string.h> | |
#include <stdio.h> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <fcntl.h> | |
#include <linux/input.h> | |
#include <linux/uinput.h> | |
#include <stdio.h> | |
#include <sys/time.h> | |
#include <sys/types.h> | |
#include <unistd.h> | |
// OpenNI headers | |
#include <XnOpenNI.h> | |
// NITE headers | |
#include <XnVSessionManager.h> | |
#include "XnVMultiProcessFlowClient.h" | |
#include <XnVWaveDetector.h> | |
#include "kbhit.h" | |
#include "signal_catch.h" | |
// xml to initialize OpenNI | |
#define SAMPLE_XML_FILE "../../Data/Sample-Tracking.xml" | |
static int uinp_fd = -1; | |
struct uinput_user_dev uinp; // uInput device structure | |
struct input_event event; // Input device structure | |
XnBool g_bQuit = false; | |
int setup_uinput_device() | |
{ | |
int i=0; | |
uinp_fd = open("/dev/uinput", O_WRONLY | O_NDELAY); | |
if (!uinp_fd) | |
{ | |
printf("Unable to open /dev/uinput\n"); | |
return -1; | |
} | |
memset(&uinp,0,sizeof(uinp)); // Intialize the uInput device to NULL | |
strncpy(uinp.name, "Kinect Mouse", UINPUT_MAX_NAME_SIZE); | |
uinp.id.version = 4; | |
uinp.id.bustype = BUS_USB; | |
ioctl(uinp_fd, UI_SET_EVBIT, EV_KEY); | |
ioctl(uinp_fd, UI_SET_EVBIT, EV_REL); | |
ioctl(uinp_fd, UI_SET_RELBIT, REL_X); | |
ioctl(uinp_fd, UI_SET_RELBIT, REL_Y); | |
ioctl(uinp_fd, UI_SET_KEYBIT, BTN_MOUSE); | |
ioctl(uinp_fd, UI_SET_KEYBIT, BTN_TOUCH); | |
ioctl(uinp_fd, UI_SET_KEYBIT, BTN_MOUSE); | |
ioctl(uinp_fd, UI_SET_KEYBIT, BTN_LEFT); | |
ioctl(uinp_fd, UI_SET_KEYBIT, BTN_MIDDLE); | |
ioctl(uinp_fd, UI_SET_KEYBIT, BTN_RIGHT); | |
ioctl(uinp_fd, UI_SET_KEYBIT, BTN_FORWARD); | |
ioctl(uinp_fd, UI_SET_KEYBIT, BTN_BACK); | |
write(uinp_fd, &uinp, sizeof(uinp)); | |
if (ioctl(uinp_fd, UI_DEV_CREATE)) | |
{ | |
printf("Unable to create UINPUT device."); | |
return -1; | |
} | |
return 1; | |
} | |
void move_cursor(int x, int y ) | |
{ | |
memset(&event, 0, sizeof(event)); | |
gettimeofday(&event.time, NULL); | |
event.type = EV_REL; | |
event.code = REL_X; | |
event.value = x; | |
write(uinp_fd, &event, sizeof(event)); | |
event.type = EV_REL; | |
event.code = REL_Y; | |
event.value = y; | |
write(uinp_fd, &event, sizeof(event)); | |
event.type = EV_SYN; | |
event.code = SYN_REPORT; | |
event.value = 0; | |
write(uinp_fd, &event, sizeof(event)); | |
} | |
//----------------------------------------------------------------------------- | |
// Callbacks | |
//----------------------------------------------------------------------------- | |
// Callback for when the focus is in progress | |
void XN_CALLBACK_TYPE SessionProgress(const XnChar* strFocus, const XnPoint3D& ptFocusPoint, XnFloat fProgress, void* UserCxt) | |
{ | |
printf("Session progress (%6.2f,%6.2f,%6.2f) - %6.2f [%s]\n", ptFocusPoint.X, ptFocusPoint.Y, ptFocusPoint.Z, fProgress, strFocus); | |
} | |
// callback for session start | |
void XN_CALLBACK_TYPE SessionStart(const XnPoint3D& ptFocusPoint, void* UserCxt) | |
{ | |
printf("Session started. Please wave (%6.2f,%6.2f,%6.2f)...\n", ptFocusPoint.X, ptFocusPoint.Y, ptFocusPoint.Z); | |
} | |
// Callback for session end | |
void XN_CALLBACK_TYPE SessionEnd(void* UserCxt) | |
{ | |
printf("Session ended. Please perform focus gesture to start session\n"); | |
} | |
// Callback for wave detection | |
void XN_CALLBACK_TYPE OnWaveCB(void* cxt) | |
{ | |
printf("Wave!\n"); | |
} | |
// callback for a new position of any hand | |
void XN_CALLBACK_TYPE OnPointUpdate(const XnVHandPointContext* pContext, void* cxt) | |
{ | |
//printf("%d: (%f,%f,%f) [%f]\n", pContext->nID, pContext->ptPosition.X, pContext->ptPosition.Y, pContext->ptPosition.Z, pContext->f | |
Time); | |
//printf("%f,%f,%f\n", pContext->ptPosition.X, pContext->ptPosition.Y, pContext->ptPosition.Z); | |
move_cursor((int)(pContext->ptPosition.X/4),(int) -(pContext->ptPosition.Y/4)); | |
} | |
//----------------------------------------------------------------------------- | |
// Main | |
//----------------------------------------------------------------------------- | |
// this sample can run either as a regular sample, or as a client for multi-process (remote mode) | |
int main(int argc, char** argv) | |
{ | |
xn::Context context; | |
XnVSessionGenerator* pSessionGenerator; | |
XnBool bRemoting = FALSE; | |
if (argc > 1) | |
{ | |
// remote mode | |
context.Init(); | |
printf("Running in 'Remoting' mode (Section name: %s)\n", argv[1]); | |
bRemoting = TRUE; | |
// Create multi-process client | |
pSessionGenerator = new XnVMultiProcessFlowClient(argv[1]); | |
XnStatus rc = ((XnVMultiProcessFlowClient*)pSessionGenerator)->Initialize(); | |
if (rc != XN_STATUS_OK) | |
{ | |
printf("Initialize failed: %s\n", xnGetStatusString(rc)); | |
delete pSessionGenerator; | |
return 1; | |
} | |
} | |
else | |
{ | |
// Local mode | |
// Create context | |
XnStatus rc = context.InitFromXmlFile(SAMPLE_XML_FILE); | |
if (rc != XN_STATUS_OK) | |
{ | |
printf("Couldn't initialize: %s\n", xnGetStatusString(rc)); | |
return 1; | |
} | |
// Create the Session Manager | |
pSessionGenerator = new XnVSessionManager(); | |
rc = ((XnVSessionManager*)pSessionGenerator)->Initialize(&context, "Click", "RaiseHand"); | |
if (rc != XN_STATUS_OK) | |
{ | |
printf("Session Manager couldn't initialize: %s\n", xnGetStatusString(rc)); | |
delete pSessionGenerator; | |
return 1; | |
} | |
// Initialization done. Start generating | |
context.StartGeneratingAll(); | |
} | |
// Register session callbacks | |
pSessionGenerator->RegisterSession(NULL, &SessionStart, &SessionEnd, &SessionProgress); | |
// Start catching signals for quit indications | |
CatchSignals(&g_bQuit); | |
// init & register wave control | |
XnVWaveDetector wc; | |
wc.RegisterWave(NULL, OnWaveCB); | |
wc.RegisterPointUpdate(NULL, OnPointUpdate); | |
pSessionGenerator->AddListener(&wc); | |
printf("Please perform focus gesture to start session\n"); | |
printf("Hit any key to exit\n"); | |
setup_uinput_device(); | |
// Main loop | |
while ((!_kbhit()) && (!g_bQuit)) | |
{ | |
if (bRemoting) | |
{ | |
((XnVMultiProcessFlowClient*)pSessionGenerator)->ReadState(); | |
} | |
else | |
{ | |
context.WaitAndUpdateAll(); | |
((XnVSessionManager*)pSessionGenerator)->Update(&context); | |
} | |
} | |
delete pSessionGenerator; | |
context.Shutdown(); | |
ioctl(uinp_fd, UI_DEV_DESTROY); | |
close(uinp_fd); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi,
Thanks for sharing above code.
Since the arguments to the move_cursor(x,y) function are relative displacements, I found the following as working correctly(instead of the definition above):
static int prev_x_pos=0;
static int prev_y_pos=0;
// callback for a new position of any hand
void XN_CALLBACK_TYPE OnPointUpdate(const XnVHandPointContext* pContext, void* cxt)
{
move_cursor((int)(pContext->ptPosition.X-prev_x_pos),(int) -(pContext->ptPosition.Y-prev_y_pos));
prev_x_pos=pContext->ptPosition.X;
prev_y_pos=pContext->ptPosition.Y;
return;
}