在OpenNI 环境下控制Kinect的其他硬体功能
之前已经有写了一篇《使用OpenNI控制Kinect的马达》,大概讲了一下怎么透过OpenNI提供的USB控制介面、来操作Kinect的马达了。虽然不算是OpenNI的标准功能,但是应该也是可以跨平台使用的方法了~
而这一篇,Heresy则是试着根据OpenKinect网页上提供的USB Protocol Documentation、基于之前写出来的KinectMotors,把剩下的功能也附加上去;整个的功能包括了:
- 控制Kinect 的马达
- 控制Kinect 上的LED 灯
- 读取Kinect 的角度、马达状态、以及加速度感应器(accelerometer)的资料
基本上,全部的功能可以写成单一档案,这边不贴完整的原始码了,有需要的人请到[这里]下载0.1版的「KinectControl.h」这个header档来使用。
它里面只有一个类别:KinectControl,内容大致如下:
class KinectControl { public : enum LED_STATUS { LED_OFF = 0, LED_GREEN = 1, LED_RED = 2, LED_YELLOW = 3, LED_BLINK_YELLOW = 4, LED_BLINK_GREEN = 5, LED_BLINK_RED_YELLOW = 6 }; enum MOTOR_STATUS { MOTOR_STOPPED = 0x00, MOTOR_LIMIT = 0x01, MOTOR_MOVING = 0x04, MOTOR_UNKNOWN = 0x08 }; public : KinectControl(); ~KinectControl(); XnStatus Create(); void Release(); XnStatus SetLED( LED_STATUS eStatus ); XnStatus Move( int angle ); int GetAngle() const ; MOTOR_STATUS GetMotorStatus() const ; XnVector3D GetAccelerometer() const ; XnStatus GetInformation( int & rAngle, MOTOR_STATUS & rMotorStatus, XnVector3D & rVec ) const ; };
基本上目前的KinectControl只会控制第一个Kinect,本来是有想透过OpenNI的xn::Device来做个别装置的区隔的,不过目前还不知道该怎么做…
而基本的设定的部分,大致如下:
KinectControl xKinectControl; if ( xKinectControl.Create() == XN_STATUS_OK ) { xKinectControl.Move( -10 ); xKinectControl.SetLED( KinectControl::LED_RED ); xKinectControl.Release(); }
首先是建立一个KinectControl的物件、xKinectControl来进行操作。
而接下来主要是模仿OpenNI的介面设计,所以是使用Create()这个函式,来做初始化;要结束的时候,则是呼叫Release()这个函式。
初始化成功后,可以透过Move()来设定Kinect的角度、透过SetLED()来设定Kinect的LED灯号。灯号状态有六种,这边是用列举型别LED_STATUS来定义;像以上面的范例来说,就是让Kinect的LED显示红色。
另外,这次也加上了资讯取得的功能,包括了Kinect 目前的角度、马达的状态、以及装置内部的加速度感应器的向量。基本上,所有的实作都是在GetInformation()这个函式里,他可以一次取得上述三种资料;它的使用方法如下:
KinectControl xKinectControl; if ( xKinectControl.Create() == XN_STATUS_OK ) { int iA; KinectControl::MOTOR_STATUS eStatus; XnVector3D vVec; xKinectControl.GetInformation( iA, eStatus, vVec ); cout << "Angle: " << iA << endl; cout << "Motor Status:" << eStatus << endl; cout << "Acc Vector: " << vVec.X << "/" << vVec.Y << "/" << vVec.Z << endl; xKinectControl.Release(); }
其中,iA就是目前的角度,值会是64 ~ -63之间的数值;如果是64度,基本上应该是代表已经超出可表示范围了。
马达状态的eStatus是一个列举型别MOTOR_STATUS,基本上有三种值:已停止(MOTOR_STOPPED)、已到达极限(MOTOR_LIMIT)、移动中(MOTOR_MOVING);虽然还有一个未知状态(MOTOR_UNKNOWN),不过那只是用来防止错误用的,应该不会出现。
最后一项型别是XnVector3D的vVec,是从加速度感应器读取出来的向量;说实话,Heresy只知道他应该是用来计算Kinect目前的绝对角度用的,但是这个向量的代表意义是什么, Heresy则是不太确定…
而如果只是要存取其中几项数值的话,也可以透过GetAngle()、GetMotorStatus()、GetAccelerometer()来单独取得其中一项资料。不过实际上,这三个函式内部都还是去呼叫GetInformation()就是了。
这篇大概就先这样了。这东西Heresy 自己很清楚,写的不是很完备,可能还会有些小问题,不过基本上在只有单台Kinect 的情况下,应该是可以用的东西。有兴趣、有需要的人,可以拿去玩看看,如果有什么问题、或是修改的建议,也欢迎提供~
本文转自http://kheresy.wordpress.com/2012/02/24/control_kinect_hardware_under_openni/