• gstcam开发(ROS+gstreamer)


    写在前面

    gstcam是github上一个开元的ros软件包,它巧妙地将gstream流媒体框架引入ROS系统。通过利用 gstreamer 实现一个标准的ROS API接口.比如捕获usb uav camera 的图像,然后转化成 ros中 sensor_msgs/Image类型的image话题,发布到ros中,供其他节点使用。

    gscam_github
    gscam_wiki
    这里注意区别在ros中处理图像的其他的几种方式
    opencv + ros 实现采集图像发布成话题
    web_video_server功能包的使用 实现把话题传到网络

    web_video_server功能包的主要功能是,在ROS系统中,比如某些话题发布了图像、视频的话题,通过这个功能包可以订阅这些话题,然后对图像压缩,通过网络传输出去,这样我们就可以通过网络的方式获取到这些图像和话题。

    概述 gscam软件工作流程

    gscam 首先在launch文件中,通过参数gstcam_config设置一条gstreamer pipeline :

    v4l2src device=$(arg DEVICE) ! video/x-raw-rgb,framerate=$(arg FPS) ! ffmpegcolorspace

    其实这条pipeline还不完整,只有两个Elements, 一个是从设备中获取图像的v4l2src, 还有一个是颜色空间转换的ffmpegcolorspace,中间的那个是输入到ffmpegcolorspace的格式设定,最基本的其实还缺少一个sink Element, 所以gscam主要就在这里做文章,它在程序中创建了一个appsink Element,然后添加到pipeline中。
    在gstreamer中,appsrc、appsink这两个element及其重要,通过他们可以在pipeline中调用第三方的代码。gscam就是通过使用appsink, 创建了一个缓存队列buffer, 通过对内存中的这个buffer拷贝、转换成sensor_msgs/Image的。

    源码分析

    gscam.cpp 定义类  gscam.h 声明类  gscam_node.cpp创建对象,创建节点调用方法

    //GSCam::configure()
    //这些主要是获取 launch中的一些参数。
        if (!gsconfig_env && !gsconfig_rosparam_defined) {
          ROS_FATAL( "Problem getting GSCAM_CONFIG environment variable and 'gscam_config' rosparam is not set. This is needed to set up a gstreamer pipeline." );
          return false;
        } else if(gsconfig_env && gsconfig_rosparam_defined) {
          ROS_FATAL( "Both GSCAM_CONFIG environment variable and 'gscam_config' rosparam are set. Please only define one." );
          return false;
        } else if(gsconfig_env) {
          gsconfig_ = gsconfig_env;
          ROS_INFO_STREAM("Using gstreamer config from env: \""<<gsconfig_env<<"\"");
        } else if(gsconfig_rosparam_defined) {
          gsconfig_ = gsconfig_rosparam;
          ROS_INFO_STREAM("Using gstreamer config from rosparam: \""<<gsconfig_rosparam<<"\"");
        }

    //  bool GSCam::init_stream()
    //这里是gstreamer的一些常规操作
    gst_init(0,0);
    //创建 appsink element
    sink_ = gst_element_factory_make("appsink",NULL);
    gst_app_sink_set_caps(GST_APP_SINK(sink_), caps);
    //set_caps of appsink 就是指定格式,这一块写的很地道,值得借鉴
    gst_caps_unref(caps);
    
    gst_bin_add(GST_BIN(pipeline_), sink_)
    gst_element_link(outelement, sink_)
    
    //gstreamer管道好像需要时钟,这里可用选ros的 或者 gstreamer的
    ros::Time now = ros::Time::now();
    GstClockTime ct = gst_clock_get_time(clock);
    
    //创建ROS 发布者
    jpeg_pub_ = nh_.advertise<sensor_msgs::CompressedImage>("camera/image_raw/compressed",1);
    cinfo_pub_ = nh_.advertise<sensor_msgs::CameraInfo>("camera/camera_info",1);
    //根据image_encoding的方式不同,发布的话题也稍微不同
    camera_pub_ = image_transport_.advertiseCamera("camera/image_raw", 1);

    void GSCam::publish_stream()
    
    //先启动流
    gst_element_set_state(pipeline_, GST_STATE_PLAYING)
    //然后在while(ros::ok)循环中
    //取样
    GstSample* sample = gst_app_sink_pull_sample(GST_APP_SINK(sink_));
    //得到缓存buffer
    GstBuffer* buf = gst_sample_get_buffer(sample);
    GstMemory *memory = gst_buffer_get_memory(buf, 0)
    //访问内存中数据
    gst_memory_map(memory, &info, GST_MAP_READ);
    
    //数据转换
    std::copy(buf_data, (buf_data)+(buf_size),img->data.begin());
    
    //数据封装
    img->header = cinfo->header;
    img->format = "jpeg";
    img->data.resize(buf_size);
    
    //发布
    jpeg_pub_.publish(img);
    cinfo_pub_.publish(cinfo);
    
    //这里gstreamer支持了好几种编码方式,所以这个地方显得有点杂,但大致思路是一样的

    //run 就是对方法的调用,gscam_node主要就是调用这个方法
    this->configure()
    this->init_stream()
    this->publish_stream();//大循环
     this->cleanup_stream();

    gscam_cmakelist分析

    //gscam的CmakeList写的也很优秀,前面我的一篇博客专门分析过
    find_package(PkgConfig)
    
    pkg_check_modules(GSTREAMER QUIET gstreamer-0.10)
    if(NOT GSTREAMER_FOUND)
      set(GSTREAMER_VERSION_1_x TRUE)
    endif()
    if(GSTREAMER_VERSION_1_x)
      message(STATUS "gst 1.0")
      pkg_check_modules(GSTREAMER REQUIRED gstreamer-1.0)
      pkg_check_modules(GST_APP REQUIRED gstreamer-app-1.0)
    else()
      message(STATUS "gst 0.1")
      pkg_check_modules(GSTREAMER REQUIRED gstreamer-0.10)
      pkg_check_modules(GST_APP REQUIRED gstreamer-app-0.10)
    endif()

    总结

    通过对gscam的学习,确实对ros以及在ros中对图像的操作有了一定的了解,我在gscam的基础之上也做了一些延伸和拓展,gscam只是把USB camera的图像拿到,转化成topic, 我想在这里有一个数据共享,一方面转化成topic供其他node使用,同时丰富一下这个pipiline,让图像还能通过网络发送出去。

     
  • 相关阅读:
    J2EE规范
    Java Web 之 SSM笔记
    Spring 官方文档笔记
    Linux学习之路--常用配置
    Linux学习之路--常用命令讲解
    人工智能学习-第二天
    人工智能学习-第一天
    人工智能学习-专业英语单词积累
    20190603 (一)安装Scrapy的环境
    20190530 数据分析
  • 原文地址:https://www.cnblogs.com/lidabo/p/16785108.html
Copyright © 2020-2023  润新知