软件要求:Ubuntu 20.04 ros的noetic版本,我是在虚拟机vitrualbox上运行的
这几天在学ROS,跟着赵虚左老师过了一遍之后,感觉还是有很多不懂的地方,xtdrone上仿真跟着文档走了一遍,好像没学到什么东西,所以我决定想办法自己搭建一个仿真平台,至少实现定位和路径规划的功能。
定位的话,这里我想用vins-fusion来做,奈何网上的资料太少了,完全不知道该从何下手,经过几天的查找资料,我目前算是解决了这个问题。
这里跟着这个教程走就行vins-fusion环境配置、安装与测试-CSDN博客,最后在数据集上测试通过代表安装完成,vins-fusion可以在自己的工作空间下面安装。
这里我们跟着赵虚左老师的视频【Autolabor初级教程】ROS机器人入门_哔哩哔哩_bilibili,最后会得到一个类似这样的机器人

我们将原camera的位置往左移一点,然后在注释掉原carema,在原camera的位置加上IMU,它会发布名称叫imu/data的消息
- <robot name="my_sensors" xmlns:xacro="http://wiki.ros.org/xacro">
- <gazebo reference="camera">
- <material>Gazebo/Bule</material>
- <gravity>true</gravity>
- <sensor name="imu_sensor" type="imu">
- <always_on>true</always_on>
- <update_rate>100</update_rate>
- <visualize>true</visualize>
- <topic>__default_topic__</topic>
- <plugin filename="libgazebo_ros_imu_sensor.so" name="imu_plugin">
- <topicName>imu/data</topicName>
- <bodyName>imu_base</bodyName>
- <updateRateHZ>100.0</updateRateHZ>
- <gaussianNoise>0.01</gaussianNoise>
- <xyzOffset>0 0 0</xyzOffset>
- <rpyOffset>0 0 0</rpyOffset>
- <frameName>imu_base</frameName>
- </plugin>
- <pose>0 0 0 0 0 0</pose>
- </sensor>
- </gazebo>
- </robot>
由于vins-fusion除了imu还需要双目相机,所以图上那个比较大的方块就是我加上的双目相机,代码如下:
- <?xml version="1.0"?>
- <!-- 摄像头相关的 xacro 文件 -->
- <robot xmlns:xacro="http://wiki.ros.org/xacro">
- <!-- 摄像头属性 -->
- <xacro:property name="camera_length" value="0.025" /> <!-- 摄像头长度(x) -->
- <xacro:property name="camera_width" value="0.04" /> <!-- 摄像头宽度(y) -->
- <xacro:property name="camera_height" value="0.04" /> <!-- 摄像头高度(z) -->
- <xacro:property name="camera_x" value="0.06" /> <!-- 摄像头安装的x坐标 -->
- <xacro:property name="camera_y" value="0.06" /> <!-- 摄像头安装的y坐标 -->
- <xacro:property name="camera_z" value="${base_link_length / 2 + camera_height / 2}" /> <!-- 摄像头安装的z坐标:底盘高度 / 2 + 摄像头高度 / 2 -->
- <xacro:property name="camera_m" value="0.01" /> <!-- 摄像头质量 -->
-
- <!-- 摄像头关节以及link -->
- <link name="double_camera">
- <visual>
- <geometry>
- <box size="${camera_length} ${camera_width} ${camera_height}" />
- </geometry>
- <origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
- <material name="black" />
- </visual>
- <collision>
- <geometry>
- <box size="${camera_length} ${camera_width} ${camera_height}" />
- </geometry>
- <origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
- </collision>
- <xacro:Box_inertial_matrix m="${camera_m}" l="${camera_length}" w="${camera_width}" h="${camera_height}" />
-
- </link>
-
- <joint name="double_camera2base_link" type="fixed">
- <parent link="base_link" />
- <child link="double_camera" />
- <origin xyz="${camera_x} ${camera_y} ${camera_z}" />
- </joint>
-
- <!-- camera left joints and links -->
- <joint name="left_joint" type="fixed">
- <origin xyz="0 0 0" rpy="0 0 0" />
- <parent link="double_camera" />
- <child link="stereo_left_frame" />
- </joint>
- <link name="stereo_left_frame"/>
-
- <joint name="left_optical_joint" type="fixed">
- <origin xyz="0 0 0" rpy="${-pi/2} 0 ${-pi/2}" />
- <parent link="stereo_left_frame" />
- <child link="stereo_left_optical_frame" />
- </joint>
- <link name="stereo_left_optical_frame"/>
-
- <!-- camera right joints and links -->
- <joint name="right_joint" type="fixed">
- <origin xyz="0 -0.07 0" rpy="0 0 0" />
- <parent link="double_camera" />
- <child link="stereo_right_frame" />
- </joint>
- <link name="stereo_right_frame"/>
-
- <joint name="right_optical_joint" type="fixed">
- <origin xyz="0 0 0" rpy="${-pi/2} 0 ${-pi/2}" />
- <parent link="stereo_right_frame" />
- <child link="stereo_right_optical_frame" />
- </joint>
- <link name="stereo_right_optical_frame"/>
-
- <!-- stereo camera -->
- <gazebo reference="double_camera">
- <sensor type="multicamera" name="stereocamera">
- <material>Gazebo/Blue</material>
- <always_on>true</always_on>
- <update_rate>30</update_rate>
- <visualize>1</visualize>
-
- <camera name="left">
- <pose>0 0 0 0 0 0</pose>
- <horizontal_fov>1.047</horizontal_fov>
- <image>
- <width>640</width>
- <height>360</height>
- <!-- format>L_UINT8</format -->
- <format>R8G8B8</format>
- </image>
- <clip>
- <near>0.1</near>
- <far>100</far>
- </clip>
- </camera>
-
- <camera name="right">
- <pose>0 -0.07 0 0 0 0</pose>
- <horizontal_fov>1.047</horizontal_fov>
- <image>
- <width>640</width>
- <height>360</height>
- <!-- format>L_UINT8</format -->
- <format>R8G8B8</format>
- </image>
- <clip>
- <near>0.1</near>
- <far>100</far>
- </clip>
- </camera>
-
- <plugin name="stereo_camera_controller" filename="libgazebo_ros_multicamera.so">
- <cameraName>stereocamera</cameraName>
- <alwaysOn>true</alwaysOn>
- <updateRate>30</updateRate>
- <cameraName>stereocamera</cameraName>
- <imageTopicName>image_raw</imageTopicName>
- <cameraInfoTopicName>camera_info</cameraInfoTopicName>
- <frameName>camera_link_optical</frameName>
- <baseline>0.07</baseline>
- <distortion_k1>0.0</distortion_k1>
- <distortion_k2>0.0</distortion_k2>
- <distortion_k3>0.0</distortion_k3>
- <distortion_t1>0.0</distortion_t1>
- <distortion_t2>0.0</distortion_t2>
- </plugin>
- </sensor>
- </gazebo>
- </robot>
OK,现在我们已经安装好了IMU和双目相机。
在/VINS-Fusion/config/vi_car/vi_car.yaml(因为我们用的是小车,无人机去改config里面另外的文件),我们需要修改它的imu和image的topic,从这个
- imu_topic: "/imu0"
- image0_topic: "/cam0/image_raw"
- image1_topic: "/cam1/image_raw"
- output_path: "/home/tong/output/"
改成你自己的topic
- imu_topic: "/imu/data"
- image0_topic: "/stereocamera/right/image_raw"
- image1_topic: "/stereocamera/left/image_raw"
- output_path: "/home/tong/output/"
OK,现在启动VINS-Fusion(记得rosrun你刚才修改的vi_car文件)
- roslaunch vins vins_rviz.launch
- rosrun vins vins_node ~/你自己的workspace/src/VINS-Fusion/config/vi_car/vi_car.yaml

可以看到目前是已经跑通的状态,但是现在移动小车就会发现,轨迹很不准确,这是因为相机的内参和外参还没改 。
在我们刚才修改的vi_car.yaml文件中,我们会找到这个:
- cam0_calib: "cam0_mei.yaml"
- cam1_calib: "cam1_mei.yaml"
说明我们要修改这两个文件,这两个文件正好就在vi_car.yaml的目录下。
打开仿真环境,使用rostopic list
可以看到有这些

通过 /stereocamera/left/camera_info 和 /stereocamera/right/camera_info 话题查看相机内参, 由于是仿真环境, 所以左右目外参理论上是一样的

通过这个内参更改那两个文件,这是这个文件的含义:
- #######################################################################
- # Calibration Parameters #
- #######################################################################
- # These are fixed during camera calibration. Their values will be the #
- # same in all messages until the camera is recalibrated. Note that #
- # self-calibrating systems may "recalibrate" frequently. #
- # #
- # The internal parameters can be used to warp a raw (distorted) image #
- # to: #
- # 1. An undistorted image (requires D and K) #
- # 2. A rectified image (requires D, K, R) #
- # The projection matrix P projects 3D points into the rectified image.#
- #######################################################################
-
- # The image dimensions with which the camera was calibrated. Normally
- # this will be the full camera resolution in pixels.
-
- # 高 ,单位:像素
- uint32 height
- # 宽 ,单位:像素
- uint32 width
-
-
-
- # The distortion parameters, size depending on the distortion model.
- # For "plumb_bob", the 5 parameters are: (k1, k2, t1, t2, k3).
- # 畸变参数
- float64[] D
-
- # Intrinsic camera matrix for the raw (distorted) images.
- # 未做去畸变处理图像的内参
- # [fx 0 cx]
- # K = [ 0 fy cy]
- # [ 0 0 1]
- # Projects 3D points in the camera coordinate frame to 2D pixel
- # coordinates using the focal lengths (fx, fy) and principal point
- # (cx, cy).
- float64[9] K # 3x3 row-major matrix
-
- # Rectification matrix (stereo cameras only)
- # 仅用于立体相机,通常是多目相机
- # 用于极线对齐
- # A rotation matrix aligning the camera coordinate system to the ideal
- # stereo image plane so that epipolar lines in both stereo images are
- # parallel.
- float64[9] R # 3x3 row-major matrix
-
- # Projection/camera matrix
- # 投影矩阵:去畸变,修正后世界坐标系下的三维坐标点投影到像素坐标系下的二维点
- # [fx' 0 cx' Tx]
- # P = [ 0 fy' cy' Ty]
- # [ 0 0 1 0]
- # By convention, this matrix specifies the intrinsic (camera) matrix
- # of the processed (rectified) image. That is, the left 3x3 portion
- # is the normal camera intrinsic matrix for the rectified image.
- # It projects 3D points in the camera coordinate frame to 2D pixel
- # coordinates using the focal lengths (fx', fy') and principal point
- # (cx', cy') - these may differ from the values in K.
- # 单目相机,tx=ty=0
- # For monocular cameras, Tx = Ty = 0. Normally, monocular cameras will
- # also have R = the identity and P[1:3,1:3] = K.
- # 双目相机
- # For a stereo pair, the fourth column [Tx Ty 0]' is related to the
- # position of the optical center of the second camera in the first
- # camera's frame. We assume Tz = 0 so both cameras are in the same
- # stereo image plane. The first camera always has Tx = Ty = 0. For
- # the right (second) camera of a horizontal stereo pair, Ty = 0 and
- # Tx = -fx' * B, where B is the baseline between the cameras.
- # Given a 3D point [X Y Z]', the projection (x, y) of the point onto
- # the rectified image is given by:
- # [u v w]' = P * [X Y Z 1]'
- # x = u / w
- # y = v / w
- # This holds for both images of a stereo pair.
- float64[12] P # 3x4 row-major matrix
外参的通过ROS的TF坐标变换来获取,打开rviz,添加tf,如图所示

通过以下命令查看左, 右目相机与IMU的外参

这里我参考gazebo仿真跑VINS-Fusion双目视觉惯性SLAM_gazebo双目相机xzcro-CSDN博客,之所以用camera,是因为我当时把imu放到原camera的位置了,我也没改名字,外参的话,Translation的偏移量,下面第一个Q是四元数,可以搜一下如何使用四元数得到相机的外参矩阵,在vi_car中修改,这样的话,我们的VINS-Fusion算是彻底跑通了。