在OpenNI 环境下控制Kinect的其他硬体功能

2012.02.25 No Comments

之前已经有写了一篇《使用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),不过那只是用来防止错误用的,应该不会出现。

最后一项型别是XnVector3DvVec,是从加速度感应器读取出来的向量;说实话,Heresy只知道他应该是用来计算Kinect目前的绝对角度用的,但是这个向量的代表意义是什么, Heresy则是不太确定…

而如果只是要存取其中几项数值的话,也可以透过GetAngle()GetMotorStatus()GetAccelerometer()来单独取得其中一项资料。不过实际上,这三个函式内部都还是去呼叫GetInformation()就是了。


这篇大概就先这样了。这东西Heresy 自己很清楚,写的不是很完备,可能还会有些小问题,不过基本上在只有单台Kinect 的情况下,应该是可以用的东西。有兴趣、有需要的人,可以拿去玩看看,如果有什么问题、或是修改的建议,也欢迎提供~

本文转自http://kheresy.wordpress.com/2012/02/24/control_kinect_hardware_under_openni/

Related Posts:
Leave a Reply
You must be logged in to post a comment.