ROS系统学习9—节点间的内存共享(中级篇)—图像收发

123
0
2021年1月28日 09时09分

前篇文章介绍了如何实现最简单的节点间内存共享。但因为篇幅所限,并没有深入介绍怎么将其实用化。本篇我们将用之前专门介绍的循环队列内存共享技术,将一个节点的图像数据直接共享给另外的节点。

 

为了比较内存共享机制和ROS自带的话题传输机制,本文用:ROS系统学习5—OpenCV的使用这篇文章提供的图像发送和接收节点做对比。结果发现用自带的话题传输机制传一张1080p的图像延时大概在600ms,而用内存共享机制传输延时只有10ms左右,性能相差了几十倍。

 

另外,ROS自身也提供了nodelet做内存共享,只是本人研究了几天发现特别乱就放弃了,感觉这东西迟早要被抛弃(事实上ROS2.0就不用这种机制了),如果有老哥有兴趣也可以去研究下。

 

下面贴出实现代码,其中最重要的“shmobject.h”在循环队列内存共享已经提供过,需要的可以直接去那边下。

 

发送节点:

 

#include <ros/ros.h>
#include <image_transport/image_transport.h>
#include <opencv2/highgui/highgui.hpp>
#include <cv_bridge/cv_bridge.h>
#include <stdio.h>
#include "../../shmobject.h"
 
int main(int argc, char** argv)
{
  ros::init(argc, argv, "image_publisher");
  ros::NodeHandle nh;
 
  cv::Mat image = cv::imread("/home/weixin/图片/2.jpeg", CV_LOAD_IMAGE_COLOR);
  if(image.empty())
  {
    printf("open error\n");
  }
  shmobject shmobj(10+image.rows*image.step,10,66);//共享内存对象
  unsigned char* shmdata=NULL;
  
  ros::Rate loop_rate(1);//每秒5帧
  while (nh.ok()) 
  {
    shmdata=shmobj.requiredata();//要求数据
    if(shmdata!=NULL)
    {
        memcpy(&shmdata[10],image.data,image.rows*image.step);
        shmobj.updatashm(shmdata);//更新数据,可被读取
        ROS_INFO("I send");
    }
    ros::spinOnce();
    loop_rate.sleep();
  }
  shmobj.writerelease();
}

 

接收节点:

 

#include <ros/ros.h>
#include <image_transport/image_transport.h>
#include <opencv2/highgui/highgui.hpp>
#include <cv_bridge/cv_bridge.h>
#include "../../shmobject.h"
 
int main(int argc, char **argv)
{
  ros::init(argc, argv, "image_listener");
  ros::NodeHandle nh;
  image_transport::ImageTransport it(nh);
  shmobject shmobj(66);
 
  ros::Rate loop_rate(30);//每秒5帧
 
  cv::Mat image(1080,1920,CV_8UC3);
 
  while (nh.ok())
  {
    unsigned char *readdata= shmobj.getdataforread();
    if(readdata!=NULL)//表示已经获取到可读数据
    {
        ROS_INFO("I heard");
        memcpy(image.data,&readdata[10],image.rows*image.step);
       // cv::imshow("",image);
       // cv::waitKey(3);
       // printf("图像显示\n");
        readdata[0]=0;//读取完成标志位
    }
    else
    {
        //printf("无可读数据,请等待写入,稍候重试\n");
    }
    loop_rate.sleep();
  }
  image.release();
  ros::spin();
  shmobj.readrelease();
}

 

发表评论

后才能评论