2016-11-25 159 views
1

我正在與Windows和sdk的kinect v1傳感器的項目。我們的目標是通過ros發送來自kinect的彩色圖像,我不知道如何處理這個問題。現在我正在使用sensor_msgs/Image消息來發布RGB值。這是我到目前爲止的代碼:rosserial發佈sensor_msgs /從窗口的圖像

img.header.stamp = nh->now(); 
    img.header.frame_id = "kinect1_ref"; 
    img.height = height; 
    img.width = width;   
    img.encoding = "rgb8"; 
    img.is_bigendian = false; 
    img.step = width*3; 

    BYTE* start = (BYTE*) lockedRect.pBits; 
    img.data = new uint8_t[width*3*height]; 



    long it; 
    for (int y = 0; y < height; ++y) { 
     for (int x = 0; x < width; ++x) { 
      const BYTE* curr = start + (x + width*y)*4; 
      for(int n=0; n<3; n++){ 
       it = y*width*3 + x*3 + n; 
       img.data[it] = (uint8_t) curr[2-n]; 
      } 
     } 
    } 
    pub->publish(&img); 

在代碼中,IMG是sensor_msgs /圖像,並lockedRect.pBits是一個指針的kinect的圖像的第一個字節。據我所知,來自kinect的圖像按照從上到下的從左到右的順序逐行存儲,每個像素由代表填充字節然後是R,G和B的4個連續字節表示。

其實我很能寄這封信給羅斯,但是當我試圖用對visualizate它,我得到以下錯誤:

錯誤加載圖片:OGRE EXCEPTION。流大小與圖像中的計算圖像大小不匹配。

我非常喜歡這個,我設置的尺寸是正確的,考慮到RGB的3個通道。從BYTEuint8_t的轉換應該是微不足道的,因爲它們都是無符號字符。

PD:我知道我可以使用openni_launch從ubuntu和ros中查看kinect數據,但是由於語音識別引擎,我需要在這種情況下使用windows。

PD2:通常用於在ros中發佈圖像的cv_bridge不包含在rosserial庫中。因此,我必須從頭開始構建圖像消息(可能有另一種方法?)

任何幫助將真正appreaciated,提前謝謝!

編輯:通過rosserial窗戶生成的類別sensor_msgs /圖像信息是隻包含這個代碼:

class Image : public ros::Msg{ 
public: 
    std_msgs::Header header; 
    uint32_t height; 
    uint32_t width; 
    char * encoding; 
    uint8_t is_bigendian; 
    uint32_t step; 
    uint8_t data_length; 
    uint8_t st_data; 
    uint8_t * data; 
    virtual void serialize(unsigned char *outbuffer); 
    virtual void deserialize(unsigned char *inbuffer);} 

兩種方法進行序列化和反序列化不寫到這裏,但我居然不知道他們如何工作。

回答

0

我想知道這是如何編譯給你的。 img.datastd::vector<uint8_t>。隨着中說,試試這個:

img.header.stamp = nh->now(); 
img.header.frame_id = "kinect1_ref"; 
img.height = height; 
img.width = width;   
img.encoding = "rgb8"; 
img.is_bigendian = false; 
img.step = width * 3; 

BYTE* start = (BYTE*) lockedRect.pBits; 
img.data.resize(img.step * height); 

long it; 
for (int y = 0; y < height; ++y) { 
    for (int x = 0; x < width; ++x) { 
     const BYTE* curr = start + (x + width*y)*4; 
     for(int n=0; n<3; n++){ 
      it = y*width*3 + x*3 + n; 
      img.data[it] = (uint8_t) curr[2-n]; 
     } 
    } 
} 
pub->publish(&img); 

更新

,我發現關於rosserial_windows限制使用的協議這一信息。雖然,您正在指定高度和寬度以及步長,但序列化與這些消息變量無關。我似乎還必須在data_lendth中指定數組的長度。但這是問題。由於某些奇怪的原因,最大陣列長度限制爲uint8_t

任何數組類型T []的數組長度將需要設置變量T_length。這意味着在不更改協議的情況下不能超出uint8_t限制。

一個解決方案,但痛苦和緩慢的是將圖像分割成255字節的自定義消息和索引它們。您必須將圖像數據放在接收端,並從數據創建sensor_msgs :: Image併發布。

+0

嗨,謝謝你的回答!它實際上是以這種方式在ros中定義的。但問題是,當pkg rosserial爲windows建立庫時,它只需要消息的骨架類。因此,在我的「sensor_msgs/Image」類中,數據數組定義爲:uint8_t * data。這就是爲什麼我必須在我自己的代碼中初始化數組。如果我不這樣做,它不會編譯。 –

+0

我明白了。看起來序列化缺少一些維度。我想設置的步驟,高度和寬度不足以正確序列化。我看到這裏有兩個變量'data_length'和'st_data'。這可能是問題。 – cassinaj

+0

我發現了關於[rosserial_windows的限制](http://wiki.ros.org/rosserial/Overview/Limitations#Arrays)中使用的協議的信息。雖然,您正在指定高度和寬度以及步長,但序列化與這些消息變量無關。我似乎還必須在'data_lendth'中指定數組的長度。但這是問題。由於某些奇怪的原因,最大數組長度限制爲'uint8_t'。 – cassinaj

0

首先,感謝cassinaj,我認爲解決方案將是他提出的答案。不過,我會添加一些我在同樣情況下爲人們找到的信息。

在rosserial陣列的限制是由uint8_t這在大多數所述ROS分佈的最大的255個字節中給出。然而,這個問題已經在這個thread中被評論過,其中建議將該值增加到uint32_t。變化was done in Jade devel。因此,如果您從Jade中的rosserial生成了ros_lib庫,則數據的長度應爲uint32_t。這是現在的圖像信息生成的代碼:

class Image : public ros::Msg 
    { 
    public: 
    std_msgs::Header header; 
    uint32_t height; 
    uint32_t width; 
    const char* encoding; 
    uint8_t is_bigendian; 
    uint32_t step; 
    uint32_t data_length; 
    uint8_t st_data; 
    uint8_t * data; 
    Image(): 
    header(), 
    height(0), 
    width(0), 
    encoding(""), 
    is_bigendian(0), 
    step(0), 
    data_length(0), data(NULL) 
{ 
} 
virtual int serialize(unsigned char *outbuffer) const 
virtual int deserialize(unsigned char *inbuffer) 

我期待得到的一切現在的工作,但另一個問題出現了。儘管陣列的長度可以是很高的值,但是rosserial消息的緩衝區仍然被限制在一個較低的值。我想這是協議本身是有限的。然後,我無法發送整個480x640xRGB的圖像信息,但我可以發送圖像的一部分(8x8xRGB),就像我測試的一樣。這終於奏效了,我在rviz中形象化了圖像,沒有任何問題。

因此,正如cassinaj提出的,一種解決方案是將所有數據分成部分,然後將它們全部放在接收端。這應該是有效的,儘管聽起來真的很痛苦(如果我將圖像分成8x8部分,那麼對於單個圖像來說,大概是4800條消息!)。

出於這個原因,我想使用win_ros(適用於Windows ROS),以便通過ROS本身發送從Kinect的所有數據。可惜的是,rosserial有這些限制,因爲它很容易使用和實施。

如果有人有什麼要補充的,或者我錯過了什麼,請告訴我。任何幫助真的appreaciated!