【解放双手】Auto Lidar2Cam Calibration——相机雷达自动标定

1.准备工作

这个算法的标定板和之前使用的autoware等其他网上的方法不一样,需要特制的,板子的参数在ros的wiki里面作者有给出参数,我找了一家做木板的厂定制了一块,切掉了中间四个圆孔,然后四个正方形是自己后面一点点量出来再贴上Apriltag,这个木板是合成木,运输过来是容易有断层的,但是凑合着用了。板子的实物图和我最小标定系统如图所示。加工好以后四个角贴上的Apriltag样式需要和论文中给出的一样是不能换的。二维码我放百度网盘吧。


在这里插入图片描述

2.开始使用

2.1 相机选型与标定

如上图可知我就随便找了个实验室能用罗技的720P USB相机,使用ros的usb_cam来启动相机,由于这个程序还需要相机的内参,所以我提前用ros自带的camera_calibration使用棋盘格标定板标定了相机的内参。

2.2 打开调试按钮

打开Debug的话是可以发布相机和雷达检测的结果的方便调试,我的代码是已经打开,需要关闭的话找到velo2cam_calibration/include/velo2cam.utils.h中第30行的

#define DEBUG 1

改为

#define DEBUG 0

改完直接重新编译。

2.3 调试相机

打开一个终端,输入命令

source devel/setup.bash
roslaunch velo2cam_calibration  mono_pattern.launch camera_name:=/camera image_topic:=image_raw  frame_name:=camera_optical_link

成功的话会打开相机检测的画面,通过检测四个AprilTag,估计出四个圆心的位置。我已经打开了Debug这个画面会自动弹出的。

在这里插入图片描述

2.4 调试雷达

新打开一个终端窗口,输入指令( cloud_topic)写你的点云主题名称。

source devel/setup.bash
roslaunch velo2cam_calibration lidar_pattern.launch cloud_topic:=/sensing/lidar/pointcloud

终端会开始输出检测结果,如下图所示,可以打开rviz来查看检测。雷达检测圆洞的方法是检测断点,如果周围环境太复杂会影响检测结果,因为可以人为过滤一下。

在这里插入图片描述

再新开一个终端窗口运行:

rosrun rqt_reconfigure rqt_reconfigure

这是一个过滤器我们要把点云过滤一下,类似下图的效果图,在/lidar_pattern/zyx_filtered中只留下板子和透过圆洞打过去的点,在lidar_pattern/range_filtered_cloud中只留下板子,这样是检测效果最好的。

img

激光雷达透过圆心的激光束一定要至少3 ring,不然会检测不到圆心的。雷达这边需要时间慢慢来。过滤完之后,可以把检测结果在RVIZ中显示出来,效果如下,绿色的就是检测出来的圆心。

img

2.5 标定

确保上面雷达和相机打开检测都没问题了,再新开一个窗口:

source devel/setup.bash
roslaunch velo2cam_calibration  registration.launch sensor1_type:=mono sensor2_type:=lidar

我们用的是单目相机所以参数选择在mono如果双目的选择stereo。

一直输入Y,应该是有三次输入Y,迭代完成后会询问是否需要换一个姿态继续,就是把板子挪挪位置,可以斜起来等重复步骤2.3-2.5直到不想继续了,我做的时候按照作者提出的完成三个姿态。

2.6 检测结果

在完成标定之后会立刻在终端显示标定结果,也就是一个tf,具体的还可以在velo2cam_calibration/launch/calibrated_tf.launch中查看,他给了三个坐标系之间的静态tf,lidar先到一个旋转了一下的相机坐标,旋转的相机坐标再到相机的光心坐标,但我们需要的是lidar到camera的。我写了一个程序用来订阅这个静态tf来转换得到外参矩阵。

roslaunch velo2cam_calibration calibration_tf.launch
roslaunch tf_matrix tf_listen.launch 
/*
 * @Description: 
 * @Author: ubuntu
 * @Date: 2022/5/19 下午7:24
 * @LastEditors: ubuntu
 * @LastEditTime: 2022/5/19 下午7:24
 * @Version 1.0
 */

/**
 * @brief: 监听tf消息转换成齐次矩阵
 */

#include <TFtoMatrix/TFtoMatrix.h>

int main (int argc, char** argv) {
    ros::init(argc, argv, "tf_listener");
    ros::NodeHandle nh;

    tf::TransformListener listener;

    ros::Rate rate(10.0);
    while (nh.ok()) {
        tf::StampedTransform transform_lidar;
        tf::StampedTransform transform_cam;

        try {
            listener.lookupTransform("/lidar_link", "/rotated_camera",
                                     ros::Time(0), transform_lidar);
            listener.lookupTransform("/rotated_camera", "/camera_optical_link",
                                     ros::Time(0), transform_cam);
            Eigen::Matrix4f lidar2rotated_cam;
            Eigen::Matrix4f rotated_cam2cam;
            pcl_ros::transformAsMatrix(transform_lidar, lidar2rotated_cam);   //直接得到矩阵
            pcl_ros::transformAsMatrix(transform_cam, rotated_cam2cam);   //直接得到矩阵
            std::cout << "lidar2rotated_cam:"  <<std::endl;
            std::cout << lidar2rotated_cam  <<std::endl;
            std::cout << "rotated_cam2cam:"  <<std::endl;
            std::cout << rotated_cam2cam  <<std::endl;
            std::cout << "final:"  <<std::endl;
            std::cout << lidar2rotated_cam * rotated_cam2cam  <<std::endl;
            // std::cout << "final2:"  <<std::endl;
            // std::cout << (lidar2cam*cam2cam).inverse()  <<std::endl;
        }
        catch (tf::TransformException &ex) {
            ROS_ERROR("%s",ex.what());
            ros::Duration(1.0).sleep();
            continue;
        }
        rate.sleep();
    }
    return 0;
}

在终端会打印出一个final就是lidar到相机的外参矩阵。

在这里插入图片描述

用points2image得到的结果

在这里插入图片描述

用pixel_cloud_fusion的结果
在这里插入图片描述

总结

  • 标定板的标志一定要对应;
  • 过滤点云要保留洞透过去的点;
  • 最后得到的tf要转化为齐次矩阵来检验下过。

3.Calibration by New in Gazebo

3.1 遇到的问题

作者是在Gazebo7上面搭建的仿真环境,ros melodic的话是Gazebo9了需要调整一下API的函数才能编译成功。

编译的时候会有类似如下的错误:

这个就是Gazebo的版本冲突问题,翻阅github issue以及Gazebo的官方github代码一点点把参数改了。

3.2 Gazebo 仿真

在这里插入图片描述
在这里插入图片描述


在这里插入图片描述
在这里插入图片描述
最终得到的精度和Ground Truth相比观察平移矩阵x,y,z误差几乎在0.01m范围内,是可接受范围,欧拉角因为我是放平的旋转标定出来也几乎为0。

雷达相机标定是将雷达相机的坐标系进行对齐,以便于将雷达相机获取的数据进行融合。在Python中,可以使用OpenCV库进行雷达相机标定。 具体步骤如下: 1. 收集雷达相机的数据,包括雷达点云和相机图像。 2. 提取雷达点云中的特征点,如角点或面点。 3. 在相机图像中检测对应的特征点。 4. 使用特定的标定算法,如Tsai算法或Zhang算法,计算雷达相机之间的转换矩阵。 5. 对标定结果进行评估和优化。 以下是一个简单的Python示例代码: ```python import cv2 import numpy as np # 读取雷达点云和相机图像 lidar_data = np.loadtxt('lidar_data.txt') img = cv2.imread('image.jpg') # 提取特征点 lidar_corners = cv2.goodFeaturesToTrack(lidar_data, 100, 0.01, 10) img_corners = cv2.goodFeaturesToTrack(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY), 100, 0.01, 10) # 计算转换矩阵 retval, camera_matrix, dist_coeffs, rvecs, tvecs = cv2.calibrateCamera([lidar_corners], [img_corners], img.shape[::-1], None, None) # 输出结果 print("Camera matrix:\n", camera_matrix) print("Distortion coefficients: ", dist_coeffs.ravel()) # 评估和优化标定结果 mean_error = 0 for i in range(len(lidar_corners)): img_points, _ = cv2.projectPoints(lidar_corners[i], rvecs[i], tvecs[i], camera_matrix, dist_coeffs) error = cv2.norm(img_corners[i], img_points[0], cv2.NORM_L2) / len(img_points) mean_error += error print("Mean error: ", mean_error/len(lidar_corners)) ```
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值