Skip to content

Instantly share code, notes, and snippets.

@trtg
Created October 20, 2012 09:17
Show Gist options
  • Save trtg/3922745 to your computer and use it in GitHub Desktop.
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
/****************************************************************************
* *
* 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;
}
@pranavkantgaur
Copy link

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;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment