当前位置:   article > 正文

激光雷达和相机联合标定保姆级教程_ros2单目相机和激光雷达联合标定

ros2单目相机和激光雷达联合标定

1、标定准备


(1)标定板选择,棋盘格标定板,一定要长方形,否则会导致后续标定时标定工具无法判断方向。且标定板尽可能大,雷达扫描的会更准确。

(2)准备rosbag包

首先,需要开雷达驱动和相机驱动,然后检查雷达话题和相机话题,我的是rslidar_points和usb_cam/image_raw,然后使用录制指令,需要将雷达和相机话题更换为你自己的。

rosbag record /rslidar_points /usb_cam/image_raw

 需要注意激光雷达和相机的采样频率不一样,导致点云和图像不能帧间匹配,网上有很多方法,1、使用GPS对时间进行硬同步。2、可以使用抽帧的方法进行时间软同步。

  解决时间同步的问题很简单,我用了一个很笨的办法,我使用rosbag实现“拍照”的效果。即对每一次标定板的姿态录一个bag包,取点云和图像的第一帧,从而达到点云和图像匹配的效果。

对标定板每个姿态录了包之后用下面的代码将rosbag转换为img和pcd的格式,从而实现了一对点云-图像对,重复上述操作,。就能得到n对点云-图像对。

代码使用教程:创建文件夹,在文件夹下创建extract_bag.py文件和data文件夹,将下面的代码填充进extract_bag.py;在data文件夹下面创建images和pointclouds文件夹,用来保存提取的点云图像。需要修改的地方有话题,bag路径,提取bag里的点云和图像的保存路径。

  1. #! /usr/bin/python
  2. # coding=utf-8
  3. import os
  4. import rosbag
  5. import cv2
  6. from cv_bridge import CvBridge
  7. from tqdm import tqdm
  8. class ExtractBagData(object):
  9. def __init__(self, bagfile_path, camera_topic, pointcloud_topic, root):
  10. self.bagfile_path = bagfile_path
  11. self.camera_topic = camera_topic
  12. self.pointcloud_topic = pointcloud_topic
  13. self.root = root
  14. self.image_dir = os.path.join(root, "images")
  15. self.pointcloud_dir = os.path.join(root, "pointcloud")
  16. #创建提取图片和点云的目录 ./root/images root/pointcloud
  17. if not os.path.exists(self.image_dir):
  18. os.makedirs(self.image_dir)
  19. if not os.path.exists(self.pointcloud_dir):
  20. os.makedirs(self.pointcloud_dir)
  21. def extract_camera_topic(self):
  22. bag = rosbag.Bag(self.bagfile_path, "r")
  23. bridge = CvBridge()
  24. bag_data_imgs = bag.read_messages(self.camera_topic)
  25. index = 0
  26. pbar = tqdm(bag_data_imgs)
  27. for topic, msg, t in pbar: # type: ignore
  28. pbar.set_description("Processing extract image id: %s" % (index+1))
  29. cv_image = bridge.imgmsg_to_cv2(msg, "bgr8")
  30. # 如果你需要使用时间戳对提取的图片命名,可以使用msg.header.stamp.to_sec()获取时间戳
  31. timestr = "%.6f" % msg.header.stamp.to_sec()
  32. cv2.imwrite(os.path.join(self.image_dir, str(timestr) + ".jpg"), cv_image) # type: ignore
  33. index += 1
  34. def extract_pointcloud_topic(self):
  35. '''
  36. # 提取点云数据为pcd后缀文件,默认提取以为时间戳命名
  37. # 提取命令:rosrun pcl_ros bag_to_pcd result.bag /velodyne_points ./pointcloud
  38. # 提取点云以时间戳命令:1616554905.476288682.pcd
  39. :return:
  40. '''
  41. cmd = "rosrun pcl_ros bag_to_pcd %s /rslidar_points %s" % (self.bagfile_path, self.pointcloud_dir)
  42. os.system(cmd)
  43. # 再读取提取的pcd点云数据,把文件名修改为按照顺序索引名
  44. #pcd_files_list = os.listdir(self.pointcloud_dir)
  45. # 因为提取的pcd是以时间戳命令的,但是存放到列表中并不是按照时间戳从小到大排列,这里对时间戳进行重新排序
  46. #pcd_files_list_sorted = sorted(pcd_files_list)
  47. # print(zip(pcd_files_list, pcd_files_list_sorted))
  48. #index = 0
  49. #pbar = tqdm(pcd_files_list_sorted)
  50. #for pcd_file in pbar:
  51. # pbar.set_description("Processing extract poindcloud id: %s" % (index + 1))
  52. # os.rename(os.path.join(self.pointcloud_dir, pcd_file),
  53. # os.path.join(self.pointcloud_dir, str(index) + ".pcd"))
  54. # print("pcd_file name: ", pcd_file)
  55. # index += 5
  56. if __name__ == '__main__':
  57. #需要处理的bag包的路径
  58. bagfile_path = '/media/happy406/046dcd53-ee66-4d3b-b556-5f9559acab84/0508/55.bag'
  59. camera_topic = "/usb_cam/image_raw"
  60. pointcloud_topic = "/rslidar_points"
  61. #将bag转换为pcd和jpg格式的保存路径
  62. extract_bag = ExtractBagData(bagfile_path, camera_topic, pointcloud_topic, "/media/happy406/046dcd53-ee66-4d3b-b556-5f9559acab84/0508")
  63. extract_bag.extract_camera_topic()
  64. extract_bag.extract_pointcloud_topic()

2、使用标定工具

1、打开matlab(我的是2023a版本,2022版以上才有联合标定工具),打开标定工具。

标定工具重点项讲解:

Open Session:打开保存过的会话

Import:导入点云-图像对

Compute Intrinsic:导入数据后自动计算相机内参

Use Fixed Intrisic:使用修正后的相机内参,这项可以通过matlab的相机标定工具来标定,然后将内参导出至matlab工作区,再导入到联合标定工具中。一般来说,可以直接使用联合标定工具计算的内参。

Edit ROI:感兴趣区域的选择,这一步可以不做更改

Select Checkboard:选择棋盘格,导入数据后会有很多不符合要求的图像点云对,此时需要手动选择棋盘格,相当于告诉标定工具,棋盘格在哪。(这一步尤为关键!!)

Cluster Threshold:聚类阈值

Dimension Tolerance:尺寸误差容忍度,设置为0.2。容忍度越高,被接受的数据越多,但是过大的容忍度也会导致后续标定误差过大

Detect:检测数据是否能被检测到棋盘格。

Calibrate:开始标定。

2、流程:

(1)导入数据,Square size是标定板的每格的长宽大小。

(2)导入后没有任何可接受的数据,这时需要调整聚类阈值和误差容忍度。

(3)选择棋盘格,一张一张的选择标定板,弄完后,apply,再detect一下,检查有多少数据被接受。标完后最好save session,不然等下筛选标定数据后又要重新选择棋盘格,会很麻烦。

我因为标定板比较小,激光雷达扫描效果不好,所以录了比较多的数据。如果标定板大的话可以少录一点。

4、标定

一开始误差特别大

点击柱状线,或者拖动离群值可以选择抛弃的数据。最好一个个的删除误差比较大的数据,因为删除一个数据都可能导致整个误差有很大的波动。优先删除重投影大的数据同时旋转误差大的数据,没有这类数据就删除重投影误差大的数据。

如果数据删的都快没了。或者变得太大,那需要重新调整,打开刚才保存的session,继续标定,然后重复刚才的动作,一遍一遍地调整,直到误差在10左右。(这一步最关键,一定要有耐心!!

如果误差比较小了,就检查棋盘格是否完好的投在了图像上,如果基本贴合图像且误差较小,就可以直接导出标定数据了。

导入到工作区,这样就得到了我的标定数据,matlab给的是转置矩阵,使用时需转置后使用。

希 望 这 篇 博 客 能 帮 助 到 你 !

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/酷酷是懒虫/article/detail/820762
推荐阅读
  

闽ICP备14008679号