2016-11-25 5 views
1

kinect v1 센서의 창과 sdk가있는 프로젝트에서 작업하고 있습니다. 목표는 kinect에서 ro를 통해 컬러 이미지를 보내는 것입니다. using rosserial.rosserial publisher sensor_msgs/windows에서 이미지

정확히 어떻게 처리해야할지 모르겠군요. 지금은 sensor_msgs/Image 메시지를 사용하여 RGB 값을 게시하고 있습니다. 코드에서

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); 

,가 sensor_msgs/이미지 및 lockedRect.pBits는 키 넥트의 이미지의 첫 번째 바이트에 대한 포인터입니다 IMG : 이것은 내가 지금까지 가지고있는 코드입니다. 필자가 아는 한 kinect의 이미지는 왼쪽에서 오른쪽 순서로 위에서 아래로 저장되며, 각 픽셀은 R, G 및 B의 패딩 바이트를 나타내는 4 개의 순차 바이트로 표현됩니다.

는 사실 ROS이를 보낼 수 있어요,하지만 난 그것을 visualizate하려고 할 때, 나는 다음과 같은 오류 얻을 :

오류로드 이미지 : 괴물 예외. 스트림 크기가 이미지의 계산 된 이미지 크기와 일치하지 않습니다.

저는이 설정과 매우 흡사합니다. RGB의 3 개 채널을 고려하여 설정 한 크기가 정확합니다. BYTE에서 uint8_t으로의 변환은 모두 서명되지 않은 char이므로 매우 간단해야합니다.

PD : openni_launch를 사용하여 우분투 및 ros에서 kinect 데이터를 시각화 할 수 있지만이 경우 음성 인식 엔진으로 인해 창을 사용해야합니다.

PD2 : 일반적으로 ro로 이미지를 게시하는 데 사용되는 cv_bridge는 rosserial 라이브러리에 포함되어 있지 않습니다. 따라서 처음부터 이미지 메시지를 작성해야합니다 (다른 방법이있을 수 있습니까?)

도움이 될 것입니다, 사전에 감사드립니다!

편집은 Windows 용 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

알겠습니다. 직렬화에 일부 치수가 누락 된 것 같습니다. 단계, 높이 및 너비 설정 올바르게 올바르게 serialize하는 것 같아요. 여기에 두 개의 변수'data_length'와'st_data'가 있습니다. 이것들이 문제 일 수 있습니다. – cassinaj

+0

[rosserial_windows restrictions] (http://wiki.ros.org/rosserial/Overview/Limitations#Arrays)에서 사용 된 프로토콜에 대한 정보를 찾았습니다. 높이와 너비 및 단계 크기를 지정하더라도 직렬화는 이러한 메시지 변수와 관련이 없습니다. 'data_lendth'에서 배열의 길이를 지정해야하는 것 같습니다. 그러나 여기에 문제가 있습니다. 어떤 이상한 이유 때문에 최대 배열 길이는'uint8_t'로 제한됩니다. – cassinaj

0

우선, cassinaj 덕분에 솔루션이 그의 제안 된 대답 일 것이라고 생각합니다. 그러나 같은 상황에있는 사람들을 위해 찾은 정보를 추가하겠습니다.

rosserial에서 배열의 제한은에 의해 주어지며 대부분의 ros 배포본에서 최대 255 바이트입니다. 그러나이 문제는이 thread에 이미 언급되어 있으며이 값을 uint32_t으로 늘리는 것이 좋습니다. 변경 was done in Jade devel. 따라서 옥에 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) 

내가 지금 일하고 모든 것을 얻을 것으로 예상했지만, 또 다른 문제가 나타났다. 어레이의 길이가 높은 값일 수는 있지만, 장미의 메시지의 버퍼는 여전히 낮은 값으로 제한됩니다. 나는 그것이 제한된 프로토콜 자체라고 생각한다. 그런 다음 480x640xRGB의 전체 이미지 메시지를 보낼 수 없었지만 테스트 한만큼 이미지의 일부 (8x8xRGB)를 보낼 수있었습니다. 이것은 결국 효과가 있었고 rviz에서 아무런 문제없이 이미지를 시각화했습니다.

따라서 한 가지 해결책은 카시나이 제안대로 모든 데이터를 분할하여 수신자 측에 모두 넣는 것입니다. 정말 고통 스럽지만 (8x8 부분으로 이미지를 분할하면 단일 이미지의 약 4800 메시지가됩니다!)이 작업은 효과가 있습니다.

이러한 이유 때문에 kinect에서 ros 자체를 통해 모든 데이터를 보내기 위해 win_ros (windows 용 ros)를 사용하려고합니다. rosserial은 사용하기 쉽고 구현하기가 쉽지 않기 때문에 이러한 한계가 있다는 것은 유감입니다.

다른 사람이 추가해야 할 것이 있거나 뭔가 부족한 것이 있으면 알려 주시기 바랍니다. 어떤 도움이 정말로 가능합니다!