在 OpenNI 環境下控制 Kinect 的其他硬體功能

| | 7 Comments| 15:18
Categories:

之前已經有寫了一篇《使用 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 的情況下,應該是可以用的東西。有興趣、有需要的人,可以拿去玩看看,如果有什麼問題、或是修改的建議,也歡迎提供~

7 thoughts on “在 OpenNI 環境下控制 Kinect 的其他硬體功能”

  1. 试了下。
    1.LED没效果。
    2. kinectcontrol.h(197): warning C4244: “=”: 从“double”转换到“int”
    3.xKinectControl.Move( 10);
    可以正确旋转到向上10度。
    但是打印信息为
    Angle:64
    Motor Status:4 MOTOR_MOVING
    Acc:x=65493,y=775,z=18

  2. to gbadown
    1. 在 Heresy 放原始碼的地方也有 example,不知道直接用 example 的話,LED 是否可以使用?
    2. 型別轉換的警告基本上可以無視。

  3. to heresy
    就是用example.cpp
    main()改成自定名的函数,所调用的.

  4. to gbadown
    可以麻煩不要修改,直接使用 example 試試看嗎?

  5. to heresy
    直接用example 实验,灯依然无效。
    还是会偶尔出现 Angle:64

  6. to gbadown
    LED 的部分麻煩在 example 結束前設中斷點、或是加入無窮迴圈試試看。
    Heresy 的 KinectControl 在結束的時候會把 LED 燈號設定回原來的 LED_BLINK_GREEN;所以如果程式直接就結束的話,可能會完全沒有燈號改變的感覺。

發佈回覆給「gbadown」的留言 取消回覆

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *