在 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),不過那只是用來防止錯誤用的,應該不會出現。

最後一項型別是 XnVector3DvVec,是從加速度感應器讀取出來的向量;說實話,Heresy 只知道他應該是用來計算 Kinect 目前的絕對角度用的,但是這個向量的代表意義是什麼,Heresy 則是不太確定…

而如果只是要存取其中幾項數值的話,也可以透過 GetAngle()GetMotorStatus()GetAccelerometer() 來單獨取得其中一項資料。不過實際上,這三個函式內部都還是去呼叫 GetInformation() 就是了。


這篇大概就先這樣了。這東西 Heresy 自己很清楚,寫的不是很完備,可能還會有些小問題,不過基本上在只有單台 Kinect 的情況下,應該是可以用的東西。有興趣、有需要的人,可以拿去玩看看,如果有什麼問題、或是修改的建議,也歡迎提供~


OpenNI / Kinect 相關文章目錄

對「在 OpenNI 環境下控制 Kinect 的其他硬體功能」的想法

  1. 請問一下Heresy大
    馬達控制是Kinect for Xbox360與Kinect for Windows都適用的嗎?
    還是需要依據機器做調整呢?
    謝謝回答

    • 抱歉,Heresy 沒有 Kinect for Windows 的感應器可以測試。
      不過基本上,xnUSBEnumerateDevices 的參數應該是需要針對硬體作調整的。

  2. 您的檔案內有example.cpp 入原始程式檔 & KinectControl.h 匯入標頭檔

    我將兩者直接匯入

    但是卻No such file or directory why?

    • 抱歉,不知道你的「匯入」是什麼意思?

      Heresy 是把這部分的程式包成單一個 header file,理論上只要去 include 他就可以用了。
      Example 只是一個使用範例而已。

      • Heresy 大的意思是我載下來不需更動直接 include 就好? 可是她好像找不到??

        所以是執行哪個?

        • 理論上是可以直接加到現有的 OpenNI 專案中使用。
          不過請先確定你本來的 OpenNI 專案有設定正確。
          如果你只是要測試控制效果,也請自行設定好專案的 OpenNI 相關設定,包含 include path 以及 library path。

          建議:請先確認你有一個可以正常運作的 OpenNI C++ 專案,再來做這個測試。

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com 標誌

您的留言將使用 WordPress.com 帳號。 登出 /  變更 )

Google photo

您的留言將使用 Google 帳號。 登出 /  變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 /  變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 /  變更 )

連結到 %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.