rosserial publish sensor_msgs/Image from windows

rosserial publish sensor_msgs/Image from windows

本文关键字:Image from windows msgs publish sensor rosserial      更新时间:2023-10-16

我正在研究一个带有Windows的项目和Kinect V1传感器的SDK。目标是从Kinect通过ROS发送颜色图像,使用rosserial。

我不知道该如何处理。现在,我正在使用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);

在代码中, img 是传感器_MSGS/image, lockedRect.pbits 是指向Kinect图像的第一个字节的指针。据我所知,来自Kinect的图像是在从头到右顺序存储的ROW WISE,每个像素由4个顺序字节表示,代表一个填充字节,然后r,g和b。p>我实际上可以将其发送给ROS,但是当我尝试使用它来可视化时,我会收到以下错误:

错误加载图像:OGRE异常。流大小与图像中计算出的图像大小不匹配。

我对此非常叠加,考虑到RGB的3个频道,我设置的大小是正确的。从字节转换为 uint8_t 应该很琐碎,因为它们都是无符号的char。

pd:我知道我可以使用OpenNi_Launch从Ubuntu和ROS中可视化Kinect数据,但是由于语音识别引擎,我需要在这种情况下使用Windows。

pd2:通常用于在ROS中发布图像的CV_Bridge不包含在rosserial库中。因此,我必须从头开始构建图像消息(可能还有另一种方式?)

任何帮助都会真正得到认可,谢谢您!

编辑: rosserial为Windows生成的Sensor_msgs/Image Messages的类仅包含此代码:

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

序列化和估算化的方法都不在这里写,但我实际上不知道它们是如何工作的。

我想知道这是如何为您编译的。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

任何type t []的数组长度将需要设置变量t_length。这意味着如果不更改协议,您不能超过uint8_t的限制。

一种解决方案,但痛苦和缓慢的是将图像分开255个字节自定义消息并将其索引。您必须将图像数据放在接收器端,并从数据中创建一个sensor_msgs ::图像并发布。

首先,要归功于Cassinaj,我认为解决方案将是他提出的答案。我将添加我为在同一情况下发现的一些信息。

Rosserial中阵列的限制由uint8_t给出,在大多数ROS分布中,最多255个字节。但是,该问题已经在此线程中进行了评论,该线程提议将此值增加到uint32_t。更改是在Jade Devel进行的。因此,如果您从JADE中的Rosserial生成 ROS_LIB 库,则数据的Lenght应该为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具有这些限制,因为它确实很容易使用和实施。

如果有人还有其他要添加的东西,或者我缺少一些东西,请告诉我。任何帮助确实得到认可!