Gazebo中加入一个双目相机及相机参数设置

2023-05-16

ROS版本: ROS Kinetic
操作系统:Ubuntu16.04 LTS

kinect

为了在gazebo中观察并利用利用视觉进行小球的定位并与ros通信,我们需要一个深度相机,这时可以直接使用kinect并加入插件与ros通信,gazebo官方也为我们提供了这个方法
http://gazebosim.org/tutorials/?tut=ros_depth_camera
直接将Kinect的模型文件下载在

<sensor>
....
</camera>
在此处添加插件代码即可
</sendor>

但有时,我们需要得到左右目两张图像,这是,我们就需要一个双目相机模型。
##双目相机
方法类似,我们可以继续使用kinect的外观,使用一个Muticamera插件,
http://gazebosim.org/tutorials?tut=ros_gzplugins
这时只需要将上述文件的sensor部分替换为官方给出的sensor部分的代码即可。这时在rqt_image_view中可以看到left和right两张图像

注意:以上两种修改sdf文件的方法不要忘记修改模型文件夹名字,sdf文件中的model名字,以及config文件中的model名

显示

首先,用rosrun gazebo_ros gazebo命令打开gazebo之后,在新的终端输入rostopic list,我们可以看到左右目的话题都在发布,主要是以下两个话题,

/multisense_sl/camera/left/image_raw
/multisense_sl/camera/left/image_raw

我们的目的是订阅这两个话题并显示,我们先尝试订阅一个话题

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#订阅gazebo中双目相机左目的图像并显示
import rospy
import cv2
import message_filters
from cv_bridge import CvBridge, CvBridgeError
from sensor_msgs.msg import Image
#ros传感器和opencv中的图像类型转换
bridge = CvBridge()
#回调函数
def callback(left_ros_image):
    left_cv_image = bridge.imgmsg_to_cv2(left_ros_image)
    cv2.imshow('left_image',left_cv_image)
    key =cv2.waitKey(1)

if __name__ == '__main__':
    #初始化节点
    rospy.init_node('gazebo_image_sub', anonymous=True)
    #订阅左目图像
    left_ros_image = rospy.Subscriber("/multisense_sl/camera/left/image_raw", Image,callback)
    rospy.spin()

注意,这前两行别忘了复制,不然可能会出现编码错误

#!/usr/bin/env python
# -*- coding: utf-8 -*-

ok,接下来我们显示双目图像,我们这里用到ros的一个message_filter的包,里面有一个Time Synchronizer,可以将接收到的信息进行同步。
https://wiki.ros.org/message_filters#Time_Synchronizer

19.12.17补充:采用这种方式发现程序经常运行一会儿就会卡住,后来发现是cv2.imshow()的问题,将其注释掉,就不会卡住了。具体原因还没找到。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#订阅gazebo中双目相机的图像并显示
import rospy
import cv2
import message_filters
from cv_bridge import CvBridge, CvBridgeError
from sensor_msgs.msg import Image

bridge = CvBridge()


def callback(left_ros_image,right_ros_image):
    left_cv_image = bridge.imgmsg_to_cv2(left_ros_image)
    right_cv_image = bridge.imgmsg_to_cv2(right_ros_image)
    cv2.imshow('left_image',left_cv_image)
    cv2.imshow('right_image',right_cv_image)
    key =cv2.waitKey(1)


if __name__ == '__main__':
    rospy.init_node('gazebo_image_sub', anonymous=True)

    left_ros_image = message_filters.Subscriber("/multisense_sl/camera/left/image_raw", Image)
    right_ros_image =message_filters.Subscriber("/multisense_sl/camera/right/image_raw", Image)
    ts = message_filters.TimeSynchronizer([left_ros_image , right_ros_image], 10)
    ts.registerCallback(callback)
    # spin() simply keeps python from exiting until this node is stopped
    rospy.spin()

插件参数

ok,现在我们想试一下这个立体相机能不能工作,我们需要知道我们到底对这个相机做了什么。介绍这部分之前,可以先看看有关相机镜头畸变和矫正相关的内容。这里在代码中对其进行注释。以下是整个立体相机的module.sdf文件。

<?xml version="1.0" ?>
<sdf version="1.5">
  <model name="Stere_camera">
    <static>True</static>
    <pose>0 0 0.2 0 0 3.14</pose>

开始module标签定义了模型的名字,pose标签指定初始位置,这里我理解的是相对于gazebo中的世界坐标系。static可省略,这里让其为True是想让相机不借助其他模型悬浮在空中。

    <link name="link">
      <inertial>
        <mass>0.1</mass>
      </inertial>
      <collision name="collision">
        <geometry>
          <box>
            <size>0.073000 0.276000 0.072000</size>
          </box>
        </geometry>
      </collision>
      <visual name="visual">
        <geometry>
          <mesh>
            <uri>model://kinect/meshes/kinect.dae</uri>
          </mesh>
        </geometry>
      </visual>

以上主要是三个标签,inertial中定义了模型质量(但由于我们将static设置为True这里相机将不受重力影响)。collision定义其物理属性,指的是在和其他物体碰撞时,以geometry中的属性进行碰撞。而visual标签中的geometry是指视觉效果。(我目前的理解是这样,如果visual中定以为球,而collision中定义为正方体,给这个物体一个力他会滑动,而不是滚动。因为collison中定义的是物理形状,而visual只是视觉形状)

      <sensor type="multicamera" name="stereo_camera">
      <update_rate>30.0</update_rate>
      <camera name="left">
        <horizontal_fov>1.3962634</horizontal_fov>
        <image>
          <width>800</width>
          <height>800</height>
          <format>R8G8B8</format>
        </image>
        <clip>
          <near>0.02</near>
          <far>300</far>
        </clip>
        <noise>
          <type>gaussian</type>
          <mean>0.0</mean>
          <stddev>0.007</stddev>
        </noise>
      </camera>
      <camera name="right">
        <pose>0 -0.07 0 0 0 0</pose>
        <horizontal_fov>1.3962634</horizontal_fov>
        <image>
          <width>800</width>
          <height>800</height>
          <format>R8G8B8</format>
        </image>
        <clip>
          <near>0.02</near>
          <far>300</far>
        </clip>
        <noise>
          <type>gaussian</type>
          <mean>0.0</mean>
          <stddev>0.007</stddev>
        </noise>
      </camera>

以上是两个传感器,我们可以看到是两个相同的传感器,其定义的属性从标签上就能看出来,这里重点是三个标签,clip中定义了相机能看到的最远和最近位置(现实中因为你焦点的原因,相机看物体模糊但也不至于看不到,所以搞不太懂这个标签的物理意义)。nosie是像素上的噪声,结合实际相机,很容易理解。最后重点说一下pose我们发现left相机是没有pose标签的,默认为0 0 0 0 -0 0,而right相机有个-0.07,负号说明其在右边,0.07就是指的基线的距离。(在这里这个pose还不知道具体是什么,是相机坐标系的原点,还是图像坐标系的远点,在深度上相差一个焦距的距离。关于这两个坐标系,见
https://blog.csdn.net/chentravelling/article/details/53558096)
这个是我们进行立体计算时需要用到的。这时我们发现对于一个镜头来说还需要一个很重要的参数,那就是焦距。但这里并没有给出,实际上我们可以根据水平视场horizontal_fov来计算出来的,参考以下两个介绍:
http://playerstage.sourceforge.net/wiki/GazeboProblemResolutionGuide
https://answers.ros.org/question/12658/how-to-change-gazebo-gui-focal-lengthfov/
即可以通过以下公式得到焦距:
flength = (width/2)/tan(hfov/2)

      <plugin name="stereo_camera_controller" filename="libgazebo_ros_multicamera.so">
        <alwaysOn>true</alwaysOn>
        <updateRate>0.0</updateRate>
        <cameraName>multisense_sl/camera</cameraName>
        <imageTopicName>image_raw</imageTopicName>
        <cameraInfoTopicName>camera_info</cameraInfoTopicName>
        <frameName>left_camera_optical_frame</frameName>
        <!--<rightFrameName>right_camera_optical_frame</rightFrameName>-->
        <hackBaseline>0.07</hackBaseline>
        <distortionK1>0.0</distortionK1>
        <distortionK2>0.0</distortionK2>
        <distortionK3>0.0</distortionK3>
        <distortionT1>0.0</distortionT1>
        <distortionT2>0.0</distortionT2>
      </plugin>
    </sensor>
    </link>
  </model>
</sdf>

以上是传感器插件,我们发现和单目相机的插件很像,主要说下最后几个参数,如果做过单目相机矫正就很容易理解(K1 K2 T1 T2 K3)是相机的畸变系数,这里使其为0,即认为相机没有畸变,理想化了。hackBaseline这里现在也没太搞懂是啥,需要再研究一下。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Gazebo中加入一个双目相机及相机参数设置 的相关文章

随机推荐

  • 【自学Docker 】Docker port命令

    Docker port命令 概述 docker port命令教程 docker port 命令可以用于列出指定的 Docker容器 的端口映射 xff0c 或者将容器里的端口映射到宿主机 该命令后面的 CONTAINER 可以是容器Id x
  • 【自学Docker】Docker pull命令

    大纲 Docker pull命令 docker pull命令教程 docker pull 命令用于从镜像仓库中拉取或者更新指定镜像 docker pull 命令中的 name 即镜像名称后面可以跟上镜像标签或者镜像摘要 docker pul
  • 【自学Docker】Docker push命令

    大纲 Docker push命令 docker push命令教程 docker push 命令用于将本地的 Docker镜像 上传到 Docker镜像仓库 docker push命令使用之前需要要先登陆到镜像仓库 docker push命令
  • 【自学Linux】Linux运行级别

    Linux运行级别 Linux运行级别教程 Linux 可以支持运行级别的设置 xff0c 运行级别就是操作系统当前正在运行的功能级别 xff0c 级别是从 0 到 6 Centos7 系统之前的版本是通过 etc inittab 文件来定
  • 【自学Linux】 Linux文件目录结构

    Linux文件目录结构 Linux文件目录结构教程 在 Linux 中 xff0c 有一个很经典的说法 xff0c 叫做一切皆文件 xff0c 因此 xff0c 我们在系统学习 Linux 之前 xff0c 首先要了解 Linux 的文件目
  • 【自学Linux】Linux一切皆文件

    Linux一切皆文件 Linux一切皆文件教程 Linux 中所有内容都是以文件的形式保存和管理的 xff0c 即一切皆文件 xff0c 普通文件是文件 xff0c 目录是文件 xff0c 硬件设备 xff08 键盘 监视器 硬盘 打印机
  • 链路聚合--Eth-Trunk

    链路聚合技术是解决二层交换机多条链路产生环路的问题 xff0c 不仅避免了环路问题 xff0c 还提高了数据的传输效率 链路聚合分为两种模式 xff1a 手动模式和LACP模式 手动模式 手动模式就是人工的方式去创建Eth Trunk和成员
  • 块元素和内联元素的特点和区别

    lt css基础之块级元素和内联元素 块级元素的特点 xff1a 1 占一整行 2 是一个矩形 3 可定义宽度和高度 xff0c 内边距 xff0c 外边距等 4 其display属性默认为block 内联元素的特点 xff1a 1 并不占
  • 在vs code中使用git

    在vs code使用git 1 下载安装git 下载地址 xff1a Git Downloads 下载后安装选择默认选项即可 2 安装完成后 xff0c 设置git的环境变量 xff1a 在系统的path环境变量中添加git exe的安装目
  • Ubuntu下压缩与解压缩

    一 linux下常用的压缩格式 linux下常用的压缩扩展名有 xff1a tar tar bz2 tar gz 二 Windows下7ZIP软件的安装 因为Linux下很多文件是bz2 gz结尾的文件 xff0c 因此需要在windows
  • VIO的图优化模型

    因子图结构 VIO在纯视觉的基础上添加了IMU约束 xff0c 因子图如下 xff1a 状态变量 VIO中 xff0c 待估计的状态变量为 i 61 R
  • CMakeLists写法总结

    个人最近学习了一些关于常见的CMakeLists的一些写法格式 xff0c 分享给大家 CMAKE MINIMUM REQUIRED VERSION xxx 该项表示要求CMAKE的最低版本号 PROJECT aim1 此项表示所建立的工程
  • Qt两种传参形式(信号槽传参、界面传参)

    一 UI界面传参 在Qt中传输数据通常有两种形式 xff0c 一种是把待传输的数据先保存到UI界面的控件中 xff0c 然后子类从界面中读取数据 使用该控件作为参数传递承载 1 首先将计算出的数值传到控件中 ui span class to
  • Intel RealSense T265 Windows10 环境下运行

    Intel RealSense T265 Windows10 环境下运行 最近从某宝上买了个T265 体验了下 intel的硬件开发 卖家怕我不会用还专门问了我会不会用 intel的包装里面不带那个很酷炫的三脚架 xff01 xff01 x
  • TB6612FNG电机驱动替代方案

    最近东芝的一个很常用的电机驱动芯片TB6612FNG停产 xff0c 这是一个全桥驱动芯片 xff0c 经过测试 xff0c 两款比较好的替代芯片有ST公司的L298系列 xff0c L293D系列和VNH5019系列的全桥驱动器 这里的完
  • 关于链表中头指针和头结点的理解

    线性表使用顺序 xff08 数组 xff09 存储时有个弊端 xff0c 那就是在插入和删除时需要大量的移动数据 xff0c 这显示是非常消耗时间的 xff0c 所以可以采用链式存储 xff0c 即有一个指针域 xff08 单链表 xff0
  • 相对深度与绝对深度,深度图与真实距离

    刚开始看单目深度估计 xff0c 好多概念都不清楚 xff0c 下面是我的理解 xff0c 有不对之处希望大佬指出 首先是相对深度和绝对深度的概念 绝对深度就是利用激光雷达等设备获取的相机与物体之间的距离 xff0c 比如KITTI数据集就
  • Gazebo和ROS通信实现发球

    ROS版本 xff1a ROS Kinetic 操作系统 xff1a Ubuntu16 04 LTS YouTube上有一个视频 xff0c 是一个乒乓球机器人在gazebo里面的方针 https www youtube com watch
  • apt: 如何通过apt-get 来安装自己的程序-----apt本地源的学习

    本文档介绍使用apt mirror软件搭建apt本地源 需求 xff1a 内网开发环境由于其特定原因不能上外网 xff0c 所以需要本地环境下的内网源来方便开发人员下载安装软件 建议 xff1a 单独使用一块磁盘来存放源文件或者单独一个目录
  • Gazebo中加入一个双目相机及相机参数设置

    ROS版本 xff1a ROS Kinetic 操作系统 xff1a Ubuntu16 04 LTS kinect 为了在gazebo中观察并利用利用视觉进行小球的定位并与ros通信 xff0c 我们需要一个深度相机 xff0c 这时可以直