雖然應該有很多人是用 Microsoft Kinect for Xbox 360 來進行 OpenNI 程式的開發,但是到目前為止,市面上 OpenNI 真正的相容裝置,其實還是只有 ASUS 的 Xtion Pro 系列,要使用 Kinect 是需要特殊修改過的驅動程式的。而在驅動程式的部分,目前大部分的開發應該都還是使用 avin2 所提供 SensorKinect 吧~
而如果是要使用 Kinect 進行程式開發的話,使用跨平台、開放原始碼的 OpenNI 和使用微軟官方的 Kinect for Windows SDK 相比,一個很大的缺點,就是功能上的不完整;這包括了聲音、以及 Kinect 上的馬達。
聲音的部分,OpenNI 本身有提供 API 來做控制,目前的問題應該是 SensorKinect 還沒有支援(有列在 todo list);而馬達的部分,OpenNI 本來的 API 並沒有支援,不過目前看來也已經是打算透過 xn::GeneralIntCapability 的形式來做支援了,只是現在還是無法使用就是了。
不過,後來才發現,在官方論壇上,已經有強者透過 OpenNI 比較低階的 USB 控制介面(XnUSB.h),來做到馬達的控制了!原文可以參考《Easy way to control Kinect motor through OpenNI》一文;而目前 OpenNI 也已經把他的程式碼放到 github 上的 Samples 裡(連結)了!
他基本上是把相關功能封包成一個 KinectMotors 的類別,把相關的控制寫成它的成員函式、以方便操作;其內容如下:
class KinectMotors { public: enum { MaxDevs = 16 }; public: KinectMotors() { m_isOpen = false; } virtual ~KinectMotors() { Close(); } bool Open() { const XnUSBConnectionString *paths; XnUInt32 count; XnStatus res; // Init OpenNI USB res = xnUSBInit(); if (res != XN_STATUS_OK) { xnPrintError(res, "xnUSBInit failed"); return false; } // Open all "Kinect motor" USB devices res = xnUSBEnumerateDevices(0x045E /* VendorID */, 0x02B0 /*ProductID*/, &paths, &count); if (res != XN_STATUS_OK) { xnPrintError(res, "xnUSBEnumerateDevices failed"); return false; } // Open devices for (XnUInt32 index = 0; index < count; ++index) { res = xnUSBOpenDeviceByPath(paths[index], &m_devs[index]); if (res != XN_STATUS_OK) { xnPrintError(res, "xnUSBOpenDeviceByPath failed"); return false; } } m_num = count; XnUChar buf[1]; // output buffer // Init motors for (XnUInt32 index = 0; index < m_num; ++index) { res = xnUSBSendControl(m_devs[index], (XnUSBControlType) 0xc0, 0x10, 0x00, 0x00, buf, sizeof(buf), 0); if (res != XN_STATUS_OK) { xnPrintError(res, "xnUSBSendControl failed"); Close(); return false; } res = xnUSBSendControl(m_devs[index], XN_USB_CONTROL_TYPE_VENDOR, 0x06, 0x01, 0x00, NULL, 0, 0); if (res != XN_STATUS_OK) { xnPrintError(res, "xnUSBSendControl failed"); Close(); return false; } } m_isOpen = true; return true; } void Close() { if (m_isOpen) { for (XnUInt32 index = 0; index < m_num; ++index) { xnUSBCloseDevice(m_devs[index]); } m_isOpen = false; } } bool Move(int angle) { XnStatus res; // Send move control requests for (XnUInt32 index = 0; index < m_num; ++index) { res = xnUSBSendControl(m_devs[index], XN_USB_CONTROL_TYPE_VENDOR, 0x31, angle, 0x00, NULL, 0, 0); if (res != XN_STATUS_OK) { xnPrintError(res, "xnUSBSendControl failed"); return false; } } return true; } private: XN_USB_DEV_HANDLE m_devs[MaxDevs]; XnUInt32 m_num; bool m_isOpen; };
而在程式裡建立一個 KinectMotors 的物件後,就可以透過他的 Move() 這個函式,來進行 Kinect 仰角的調整了!簡單的操作範例,大致上如下:
KinectMotors motors; if (!motors.Open()) return 1; motors.Move(31);
不過基本上,這個方法應該只算是一個雛形,和 OpenNI 提供的一般操作介面不完全一致;而且在這個類別裡,他基本上會根據 Vender ID 和 Product ID 把系統裡的 Kinect 馬達裝置都找出來(透過 xnUSBEnumerateDevices()),然後都開啟來控制;所以如果有使用多台 Kinect 的話,他會同時對所有的 Kinect 來進行操作!如果要個別控制的話,則是需要改寫這個類別,並針對得到的 XnUSBConnectionString 來和 xn::Device 的資訊(應該是「Create Info」、參考)做比對、以找出要控制的是哪一個 Kinect 。
另外要注意的是,由於 Kinect 內部其實還有一個加速度感應器,可以判斷自身的傾角,所以實際上這邊透過 Move() 設定的角度,會是空間中絕對的角度!也就是說,0 度的時候,Kinect 會是水平的,正值會往上抬、負值則會往下傾,直到到達目標角度為止;這是在使用時可能要注意的地方。
總之,如果有必要的話,透過這個方法應該是可以用來操作 Kinect 的馬達了~不過,還是希望 OpenNI 能趕快把 Kinect 納入正式支援吧~ ^^"
[…] 使用 OPENNI 控制 KINECT 的馬達/在 OPENNI 環境下控制 KINECT 的其他硬體功能 […]
讚讚
您好
我將github的程式在vs2010上執行
但是卻出現fatal error C1083: 無法開啟包含檔案: ‘windows.h’: No such file or directory
讚讚
你是使用 Visual Studio Express 版嗎?
如果是的話,你可能需要另外安裝 Windows SDK。
http://www.microsoft.com/en-us/download/details.aspx?id=8279
讚讚
[…] 之前已经有写了一篇《使用OpenNI控制Kinect的马达》,大概讲了一下怎么透过OpenNI提供的USB控制介面、来操作Kinect的马达了。虽然不算是OpenNI的标准功能,但是应该也是可以跨平台使用的方法了~ […]
讚讚
[…] 本文转自https://kheresy.wordpress.com/2012/02/03/control_kinect_motor_via_openni/ Tags: KinectOPENNI […]
讚讚
[…] 發表迴響 之前已經有寫了一篇《使用 OpenNI 控制 Kinect 的馬達》,大概講了一下怎麼透過 OpenNI 提供的 USB 控制介面、來操作 Kinect […]
讚讚
Protocol Documentation
http://openkinect.org/wiki/Protocol_Documentation
讚讚
這東西真厲害 直接套上很好用 終於能動角度了orz 不然實驗很累 還要自己抓角度= =
Heresy您的文章的真的非常有參考跟價值性
也很感謝您~
讚讚
也希望之後多多支持本站 :)
讚讚
請問一下我將https://github.com/manctl/openni/blob/manctl/Samples/Kinect/kinect-motors.cpp
裡面的c++程式碼丟到vs 2010執行,code沒有錯,但卻有六個不知道怎麼解掉的bug
1>isocpp.obj : error LNK2019: 無法解析的外部符號 __imp__xnUSBSendControl 在函式 “public: bool __thiscall KinectMotors::Open(void)" (?Open@KinectMotors@@QAE_NXZ) 中被參考
1>isocpp.obj : error LNK2019: 無法解析的外部符號 __imp__xnUSBOpenDeviceByPath 在函式 “public: bool __thiscall KinectMotors::Open(void)" (?Open@KinectMotors@@QAE_NXZ) 中被參考
1>isocpp.obj : error LNK2019: 無法解析的外部符號 __imp__xnUSBEnumerateDevices 在函式 “public: bool __thiscall KinectMotors::Open(void)" (?Open@KinectMotors@@QAE_NXZ) 中被參考
1>isocpp.obj : error LNK2019: 無法解析的外部符號 __imp__xnPrintError 在函式 “public: bool __thiscall KinectMotors::Open(void)" (?Open@KinectMotors@@QAE_NXZ) 中被參考
1>isocpp.obj : error LNK2019: 無法解析的外部符號 __imp__xnUSBInit 在函式 “public: bool __thiscall KinectMotors::Open(void)" (?Open@KinectMotors@@QAE_NXZ) 中被參考
1>isocpp.obj : error LNK2019: 無法解析的外部符號 __imp__xnUSBCloseDevice 在函式 “public: void __thiscall KinectMotors::Close(void)" (?Close@KinectMotors@@QAEXXZ) 中被參考
1>E:\Users\Nathaniel.Think\Documents\Visual Studio 2010\Projects\isocpp\Debug\isocpp.exe : fatal error LNK1120: 6 個無法解析的外部符號
懇請指教,謝謝
讚讚
你有 link OpenNI 的 lib 檔嗎?
讚讚