激光雷达和相机数据时间同步的几种方法

这篇具有很好参考价值的文章主要介绍了激光雷达和相机数据时间同步的几种方法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一. 引言

图1图2为数据时间未校准,使用Matlab 2022b相机和激光雷达联合标定工具箱进行的联合标定(图1为使用4对jpg和pcd文件时的联合标定效果,图2为使用15对jpg和pcd文件时的联合标定效果);图3图4为数据时间已校准后,使用Matlab 2022b相机和激光雷达联合标定工具箱进行的联合标定(图3为使用4对jpg和pcd文件时的联合标定效果,图4为使用15对jpg和pcd文件时的联合标定效果);

四种情况联合标定结果对比如表1所示。

sick激光雷达时间同步,ROS,python,自动驾驶,ubuntu,python

图1:时间未校准(4对)

sick激光雷达时间同步,ROS,python,自动驾驶,ubuntu,python

图2:时间未校准(15对)

sick激光雷达时间同步,ROS,python,自动驾驶,ubuntu,python

图3:时间已校准(4对)

sick激光雷达时间同步,ROS,python,自动驾驶,ubuntu,python

图4:时间已校准(15对)

表1:4种情况效果对比
Translation Error Rotation Error Reprojection Error
时间戳校准15对 0.0306 3.2476 5.1702
时间戳校准4对 0.0419 4.0709 7.2469
时间戳未校准15对 0.1788 13.5330 34.8668
时间戳未校准4对 0.2920 28.7961 52.3936

由表1可以看出,时间同步对于多传感器联合标定来说,具有十分重要的意义。

二. 介绍

 相机雷达时间同步(基于ROS)和 基于ROS实现多传感器时间软同步 提出的方法,是针对bag文件进行离线时间同步,并且当且仅当它们有着相同的时间戳的时候,才把它们发布出去,从而实现一定程度上的多传感器时间同步。在实际应用(本文使用Apollo D-Kit套件中的LI-USB30-AR023ZWDR相机、Velodyne VLP-16激光雷达)中,由于两者话题没有相同的时间戳,因此提取出来的bag文件是个空包。

1. 录制bag文件

rosbag record -O <包名.bag> <话题1> <话题2> ... <话题n>

 如:录制激光雷达话题/velodyne_points和相机话题/usb_cam/image_raw,并保存为001.bag:

rosbag record -O 001.bag /usb_cam/image_raw /velodyne_points

2. 显示bag文件的信息

rosbag info <包名.bag>

如:

rosbag info 001.bag

sick激光雷达时间同步,ROS,python,自动驾驶,ubuntu,python

3. 查看时间戳

roscore

rqt_bag <包名.bag>

 如:

roscore
rqt_bag 001.bag

sick激光雷达时间同步,ROS,python,自动驾驶,ubuntu,python

4. 提取带时间戳的pcd文件

rosrun pcl_ros bag_to_pcd <包名.bag> <话题名> <要保存的路径>

如:

rosrun pcl_ros bag_to_pcd 001.bag /velodyne_points /home/wrk/data_imgpcd/velodyne

sick激光雷达时间同步,ROS,python,自动驾驶,ubuntu,python

最终效果如上图所示。

三. 方法一

我没有学习过ROS,也没学习过“话题”“消息”“发布者”“订阅者”,这个只能算是笨办法:首先从bag文件中提取出带时间戳的jpg文件和pcd文件,然后将文件一起放在同一个目录下面,最后按时间戳进行排序并重新命名。

1. 提取带时间戳的jpg和pcd文件

在从.bag文件中读取并保存.jpg图片和.pcd点云中找到了提取带时间戳的jpg文件(但是pcd文件不带时间戳),所以我就在这里给它注释修改了一下:

#! /usr/bin/python
# coding=utf-8

import os
import rosbag
import cv2
from cv_bridge import CvBridge
from tqdm import tqdm

class ExtractBagData(object):

    def __init__(self, bagfile_path, camera_topic, pointcloud_topic, root):
        self.bagfile_path = bagfile_path
        self.camera_topic = camera_topic
        self.pointcloud_topic = pointcloud_topic
        self.root = root
        self.image_dir = os.path.join(root, "images")
        self.pointcloud_dir = os.path.join(root, "pointcloud")

        #创建提取图片和点云的目录 ./root/images  root/pointcloud
        if not os.path.exists(self.image_dir):
            os.makedirs(self.image_dir)
        if not os.path.exists(self.pointcloud_dir):
            os.makedirs(self.pointcloud_dir)

    def extract_camera_topic(self):
        bag = rosbag.Bag(self.bagfile_path, "r")
        bridge = CvBridge()
        bag_data_imgs = bag.read_messages(self.camera_topic)

        index = 0

        pbar = tqdm(bag_data_imgs)
        for topic, msg, t in pbar: # type: ignore
            pbar.set_description("Processing extract image id: %s" % (index+1))
            cv_image = bridge.imgmsg_to_cv2(msg, "bgr8")
            # 如果你需要使用时间戳对提取的图片命名,可以使用msg.header.stamp.to_sec()获取时间戳
            timestr = "%.6f" %  msg.header.stamp.to_sec()
            cv2.imwrite(os.path.join(self.image_dir, str(timestr) + ".jpg"), cv_image) # type: ignore
            index += 1

    def extract_pointcloud_topic(self):
        '''
        # 提取点云数据为pcd后缀文件,默认提取以为时间戳命名
        # 提取命令:rosrun pcl_ros bag_to_pcd result.bag /velodyne_points ./pointcloud
        # 提取点云以时间戳命令:1616554905.476288682.pcd
        :return:
        '''
        cmd = "rosrun pcl_ros bag_to_pcd %s /velodyne_points %s" % (self.bagfile_path, self.pointcloud_dir)
        os.system(cmd)

        # 再读取提取的pcd点云数据,把文件名修改为按照顺序索引名
        #pcd_files_list = os.listdir(self.pointcloud_dir)
        # 因为提取的pcd是以时间戳命令的,但是存放到列表中并不是按照时间戳从小到大排列,这里对时间戳进行重新排序
        #pcd_files_list_sorted = sorted(pcd_files_list)
        # print(zip(pcd_files_list, pcd_files_list_sorted))

        #index = 0
        #pbar = tqdm(pcd_files_list_sorted)
        #for pcd_file in pbar:
        #    pbar.set_description("Processing extract poindcloud id: %s" % (index + 1))
        #    os.rename(os.path.join(self.pointcloud_dir, pcd_file),
        #              os.path.join(self.pointcloud_dir, str(index) + ".pcd"))
        #    print("pcd_file name: ", pcd_file)
        #    index += 1

if __name__ == '__main__':
    bagfile_path = '/home/wrk/001.bag'
    camera_topic = "/usb_cam/image_raw"
    pointcloud_topic = "/velodyne_points"
    extract_bag = ExtractBagData(bagfile_path, camera_topic, pointcloud_topic,  "/home/wrk/data_imgpcd")
    extract_bag.extract_camera_topic()
    extract_bag.extract_pointcloud_topic()

具体使用方法:

  1. 在VScode(可以使用其他软件)中复制并粘贴以上内容;
  2. 将“bagfile_path”换成自己的包文件地址、将“camera_topic”换成自己的相机话题名、将“pointcloud_topic”换成自己的激光雷达话题名、将“extract_bag”换成自己的保存路径;
  3. 右键选择“运行python”,选择“在终端中运行python文件”。

sick激光雷达时间同步,ROS,python,自动驾驶,ubuntu,python

2. 将两种文件放在同一目录下

sick激光雷达时间同步,ROS,python,自动驾驶,ubuntu,python

3. 重命名

#coding=utf-8
import os
 
def rename(filepath):
    """
    filePath:文件目录
    return:None
    """
    filenamelist = os.listdir(filepath)
    filenamelist = sorted(filenamelist, key=lambda x: eval(x[0:-4]))
    #将filepath目录下的文件读取为列表,并排序
    
    newnamelist = ["{:0>4}".format(i) for i in range(len(filenamelist))]
    #重命名为占4个字符宽度,非零数字右对齐,其余空位用0补齐. 如"0001"、"0002"、"0099"
    for i in range(len(filenamelist)):
        old_path = os.path.join(filepath,filenamelist[i])
        #旧文件路径
        new_path = os.path.join(filepath,newnamelist[i]+filenamelist[i][-4::])
        #新文件路径(保留文件后缀)
        os.rename(old_path,new_path)
        #重命名操作
    """"""
    print("Finish")
    return None
 
rename("/home/wrk/data")

具体使用方法:

  1. 在VScode(可以使用其他软件)中复制并粘贴以上内容;
  2. 将“filepath”换成自己的目录地址;
  3. 右键选择“运行python”,选择“在终端中运行python文件”。

最终效果如下图所示:

sick激光雷达时间同步,ROS,python,自动驾驶,ubuntu,python

4. 总结

选择相邻的jpg和pcd文件,这个笨办法虽然没有写的那么漂亮,只能针对bag文件提取信息(离线使用),不能连接传感器在线实时使用,但是也基本满足我的需求了。

四. 方法二

稍微学习了一下ROS机器人操作系统,尝试自己写代码将图像数据和激光雷达数据提取出来。并根据时间戳进行命名,然后手动选取相邻的图像和激光雷达数据,以此实现时间的校准。

1. 离线读取bag数据

主要步骤为:

  1. 创建工作空间(有工作空间就忽略)
  2. 创建软件包
  3. 编译
  4. 编写py文件
  5. 编写launch文件
  6. 启动launch文件
(一). 创建工作空间:

mkdir -p 工作空间名/src

如:

mkdir -p catkin_workspace/src
(二). 创建软件包

cd ~/工作空间名/src

catkin_create_pkg <软件包名> <依赖项1> <依赖项2>  ...<依赖项n>

如:

cd ~/catkin_workspace/src
catkin_create_pkg data2jpgcsv rospy sensor_msgs cv_bridge
(三). 编译

cd ~/工作空间名/src

catkin_make

 如:

cd ~/catkin_workspace/
catkin_make
(四). 编写py文件

(1). 使用VScode,在自己“~/home/用户名/工作空间名/src/软件包”目录下创建scripts文件夹:

或:

cd ~/工作空间/src/软件包/

mkdir scripts

 (2). 在“~/home/用户名/工作空间名/src/软件包/scripts”目录下创建data2jpgcsv.py文件,并复制以下内容:

#! /usr/bin/python
# coding = utf-8

import cv2
import rospy
import numpy as np
import pandas as pd
from sensor_msgs.msg import Image
from sensor_msgs import point_cloud2
from sensor_msgs.msg import PointCloud2
from cv_bridge import CvBridge


def LidarCallBack(msg):
    if isinstance(msg, PointCloud2):
        gen = point_cloud2.read_points(msg)
        arr = []
        for p in gen:
            arr.append(p)
        arr = np.array(arr)
        pd.DataFrame(arr).to_csv("/home/wrk/data_imgcsv/{}.csv".format(msg.header.stamp))
        rospy.logwarn("Success Write in:{}.csv".format(msg.header.stamp))
    elif isinstance(msg, Image):
        cv_img = bridge.imgmsg_to_cv2(msg, "bgr8")
        cv2.imwrite("/home/wrk/data_imgcsv/{}.jpg".format(msg.header.stamp) , cv_img) # type: ignore
        rospy.loginfo("Success Write in:{}.jpg".format(msg.header.stamp))
    else:
        pass

    return None

rospy.init_node("lidar_node")
bridge = CvBridge()
camer_sub = rospy.Subscriber("/usb_cam/image_raw",Image,LidarCallBack,queue_size=10)
lidar_sub = rospy.Subscriber("/velodyne_points",PointCloud2,LidarCallBack,queue_size=10)
rospy.spin()

注:

  1. 将文件夹路径换成自己的
  2. 将相机话题、激光雷达话题换成自己的

 (3). 右键此py文件,勾选“允许作为程序执行文件”

sick激光雷达时间同步,ROS,python,自动驾驶,ubuntu,python

(五). 编写launch文件

(1). 使用VScode,在自己“~/home/用户名/工作空间名/src/软件包”目录下创建launch文件夹:

或:

cd ~/工作空间/src/软件包/

mkdir launch

 (2). 在“~/home/用户名/工作空间名/src/软件包/launch”目录下创建outline.launch文件,并复制以下内容:

<launch>

    <node pkg="rosbag" type="play" name="player" output="screen" args="--clock /home/wrk/001.bag"/>

    <node pkg="data2jpgcsv" type="data2jpgcsv.py" name="data2jpgcsv"/>

</launch>

 注:

  1. 将bag文件路径换成自己的路径
  2. 将pkg换成自己的包名,将type换成自己的文件名,将name换成自己的节点名
(六). 启动launch文件

请确保文件结构如下图所示一致:

catkin_workspace
├── build
├── devel
└── src
          ├── CMakeLists.txt -> /opt/ros/melodic/share/catkin/cmake/toplevel.cmake
          └── data2jpgcsv
                        ├── CMakeLists.txt
                        ├── launch
                        │          └── outline.launch
                        ├── package.xml
                        ├── scripts
                        │          └── data2jpgcsv.py
                        └── src

启动launch文件的命令格式:

roslaunch <软件包名> <launch文件名.launch>

 如:

roslaunch data2jpgcsv outline.launch 

2. 在线读取传感器数据

(一). 启动相机节点

ROS下usb_cam的安装

Ubuntu 18.04 下使用 RViz 显示出摄像头视频教程

使用Rviz完成摄像头(camera)的视频采集

ROS下使用摄像头

ubuntu20.04的usb_cam安装测试(亲测)

(二). 启动激光雷达节点

ubuntu20.04 ROS 环境下使用velodyne激光雷达与 Flir 工业相机

ROS采集激光雷达点云数据

Velodyne VLP-32C/VLP-16在ROS下的数据获取、显示及录制

Ubuntu18.04 运行velodyne

激光雷达Velodyne16配置及录制rosbag

(三). 启动录制节点
rosrun data2jpgcsv data2jpgcsv.py

3. 总结

离线读取bag文件和在线读取传感器数据的原理一致。区别在于,离线读取是先用launch文件启动播放bag文件,将消息发布在电脑中,然后启动节点读取数据;在线读取是启动传感器节点之后,消息同样也被发布在电脑中,然后启动节点读取转化数据。

最终效果如图所示:

sick激光雷达时间同步,ROS,python,自动驾驶,ubuntu,python

五. 方法三

从提取出来的数据可以看出,两个相邻的激光雷达数据之间有3~4个图像数据,因此我们选择激光雷达数据及其相邻的图像数据,并写入bag文件中,以此实现时间上的校准。

写入bag文件的目的,可以根据方法一进行提取出jpg和pcd文件,方便使用Matlab进行联合标定。

1. 离线读取bag数据

将bag文件读取成为新的bag文件

(一). 编写py文件

(1).  在“~/home/用户名/工作空间名/src/软件包/scripts”目录下创建data2jpgcsv.py文件,并复制以下内容:

#! /usr/bin/python
# coding = utf-8

import rospy
import rosbag
from sensor_msgs.msg import Image
from sensor_msgs.msg import PointCloud2

bag = rosbag.Bag('/home/wrk/dataset.bag','w')

k = 0

def MsgsCallBack(msg):
    global k
    if isinstance(msg, PointCloud2):
        bag.write('PointCloud2',msg)
        k = 0
    elif isinstance(msg, Image):
        k = k +1
        if k == 1:
            bag.write('Image',msg)
        else:
            pass
    else:
        pass

rospy.init_node('drone_track_data_saver')
rospy.Subscriber("/usb_cam/image_raw",Image,MsgsCallBack,queue_size=10)
rospy.Subscriber("/velodyne_points",PointCloud2,MsgsCallBack,queue_size=10)

rate = rospy.Rate(1) # 10hz
while not rospy.is_shutdown():
    rate.sleep()
else:
    bag.close()

注:

  1. 将文件夹路径换成自己的
  2. 将相机话题、激光雷达话题换成自己的

 (2). 右键此py文件,勾选“允许作为程序执行文件”

 (二). 编写launch文件

(1). 在“~/home/用户名/工作空间名/src/软件包/launch”目录下创建outline1.launch文件,并复制以下内容:

<launch>

    <node pkg="rosbag" type="play" name="player" output="screen" args="--clock /home/wrk/001.bag"/>

    <node pkg="data2jpgcsv" type="data2bag.py" name="data2bag"/>

</launch>

 注:

  1. 将bag文件路径换成自己的路径
  2. 将pkg换成自己的包名,将type换成自己的文件名,将name换成自己的节点名
(三). 启动launch文件

请确保文件结构如下图所示一致:

catkin_workspace
├── build
├── devel
└── src
          ├── CMakeLists.txt -> /opt/ros/melodic/share/catkin/cmake/toplevel.cmake
          └── data2jpgcsv
                        ├── CMakeLists.txt
                        ├── launch
                        │          └── outline.launch

                        │          └── outline1.launch
                        ├── package.xml
                        ├── scripts
                        │          └── data2jpgcsv.py

                        │          └── data2bag.py
                        └── src

启动launch文件的命令格式:

roslaunch <软件包名> <launch文件名.launch>

 如:

roslaunch data2jpgcsv outline1.launch 

2. 在线读取传感器数据

(一). 启动相机节点

ROS下usb_cam的安装

Ubuntu 18.04 下使用 RViz 显示出摄像头视频教程

使用Rviz完成摄像头(camera)的视频采集

ROS下使用摄像头

ubuntu20.04的usb_cam安装测试(亲测)

(二). 启动激光雷达节点

ubuntu20.04 ROS 环境下使用velodyne激光雷达与 Flir 工业相机

ROS采集激光雷达点云数据

Velodyne VLP-32C/VLP-16在ROS下的数据获取、显示及录制

Ubuntu18.04 运行velodyne

激光雷达Velodyne16配置及录制rosbag

(三). 启动录制节点
rosrun data2jpgcsv data2bag.py

3. 总结

离线读取bag文件和在线读取传感器数据的原理一致。区别在于,离线读取是先用launch文件启动播放bag文件,将消息发布在电脑中,然后启动节点读取数据;在线读取是启动传感器节点之后,消息同样也被发布在电脑中,然后启动节点读取转化数据。

最终效果如图所示:

sick激光雷达时间同步,ROS,python,自动驾驶,ubuntu,python文章来源地址https://www.toymoban.com/news/detail-770521.html

到了这里,关于激光雷达和相机数据时间同步的几种方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 智能车打开usb相机和激光雷达录制数据包的过程记录

    首先,智能车的遥控器启动之后,要解除驻车挡位(尾灯不亮红色才可以),然后右上角的那个拨杆是喇叭,对应的左上角的那个拨杆是控制挡位的,包括前进档,后退档。假如是前进,往上拨,这个挡杆的正下方的挡杆应该位于下方,然后拨动右边的挡杆向上拨,此时车子

    2024年02月16日
    浏览(37)
  • 激光雷达-相机联合标定

    https://f.daixianiu.cn/csdn/9499401684344864.html imu与lidar标定 https://github.com/PJLab-ADG/SensorsCalibration/blob/master/lidar2imu/README.md 多雷达标定 https://f.daixianiu.cn/csdn/3885826454722603.html ros usb相机内参标定 ROS系统-摄像头标定camera calibration_berry丶的博客-CSDN博客

    2024年02月15日
    浏览(40)
  • 3D激光雷达和相机融合

    主要看重投影误差,cv的标定识别率也太低了。。。原因是找到了,相机给的曝光时间5ms,增大曝光时间成功率大大提升,但曝光时间给打了,影响实时性,头疼。。 主要是3D-2D的标定 采集标定数据 参照以下采集标定数据和处理标定数据,pcd角点选取和图像角点选取: https:

    2024年02月06日
    浏览(57)
  • 激光雷达和相机联合标定

    所有内容仅供个人学习记录 相机内参是相机坐标系转换到图像像素坐标系 相机内参是世界坐标系转换到相机坐标系 相机的成像过程涉及到四个坐标系:世界坐标系、相机坐标系、图像坐标系、像素坐标系。 四个坐标系: 1) 世界坐标系(world coordinate system) 现实世界的三维坐

    2024年01月18日
    浏览(49)
  • 镭神激光雷达和相机联合标定

    镭神激光雷达坐标系和相机坐标系都为右手坐标系 镭神激光雷达坐标系:原点为激光雷达光学中心,右为X,前为Y,上为Z 相机坐标系:原点为相机光心,右为X,下为Y,前为Z 同时规定欧拉角:绕X轴为俯仰角(pitch),绕Y轴为翻滚角(roll),绕Z轴为偏航(航向)角(heading、yaw)。 此时

    2024年02月09日
    浏览(63)
  • Autoware实现相机和激光雷达联合标定

    1-编译 2-修改代码 打开CMakeLIsts.txt 将三处该行 if (\\\"${ROS_VERSION}\\\" MATCHES \\\"(indigo|jade|kinetic)\\\") 改为 if (\\\"${ROS_VERSION}\\\" MATCHES \\\"(indigo|jade|kinetic|melodic)\\\") 重新编译: 3-测试启动 输入命令,显示如下,则证明正常: 启动激光雷达: /velodyne_points /rslidar_points 启动相机: /camera/color/image_raw 设

    2024年01月19日
    浏览(42)
  • 深度相机和激光雷达的融合标定(Autoware)

    深度相机和激光雷达是智能汽车上常用的传感器。但深度相机具有特征难以提取,容易受到视角影响。激光雷达存在数据不够直观且容易被吸收,从而丢失信息。因此在自动驾驶领域,需要对于不同传感器做数据的融合和传感器的标定。 内参标定的原理和方法比较简单,由于

    2024年02月10日
    浏览(53)
  • python的几种时间表示方法

    一、时间的几种表示方法 time时间模块儿获取当天的时间 1、详细表示当前的时间 import time time.localtime() 2、标准输出当前时间格式 import time time.strftime(\\\"%Y-%m-%d %H:%M:%S\\\",time.localtime()) datetime时间模块儿获取当天的时间 1、详细表示当前时间 import datetime time = datetime.datetime.now() pr

    2023年04月21日
    浏览(37)
  • 使用激光雷达(LiDAR)和相机进行3D物体跟踪

    使用相机和激光雷达进行时间到碰撞(TTC)计算 在我的先前文章中,我介绍了通过检测关键点和匹配描述符进行2D特征跟踪的主题。在本文中,我将利用这些文章中的概念,以及更多的内容,开发一个软件流水线,使用相机和激光雷达测量在3D空间中检测和跟踪对象,并使用

    2024年02月05日
    浏览(46)
  • 虚拟机(Ubuntu1804)相机与激光雷达联合标定实现过程记录

    在智能小车录制的点云数据在rviz打开一定要修改Fixed Frame为laser_link,这样才能看到点云,注意此时用的是雷神激光雷达,话题名是lslidar_,可采用rostopic list查看具体名称 1、新建一个终端打开roscore 2、在文件夹libratia中新建一个终端 【注意】这里的--pause可以暂停,当后面需要

    2024年02月16日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包