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