保姆级教程:用cam_lidar_calibration搞定激光雷达与相机标定(附避坑指南)

张开发
2026/4/5 17:40:57 15 分钟阅读

分享文章

保姆级教程:用cam_lidar_calibration搞定激光雷达与相机标定(附避坑指南)
从零实现激光雷达与相机高精度标定cam_lidar_calibration实战全解析当激光雷达的点云遇上相机的像素如何让它们说同一种语言传感器标定就像给两个陌生人做翻译而外参标定决定了翻译的准确性。今天我们要拆解的cam_lidar_calibration工具正是解决这个痛点的瑞士军刀。1. 环境配置搭建标定工作台工欲善其事必先利其器。在开始标定前我们需要准备以下环境组件ROS环境推荐Melodic或Noetic版本这是标定工具运行的基石传感器驱动确保激光雷达和相机都能正常输出数据标定工具包通过以下命令安装cam_lidar_calibrationmkdir -p ~/calib_ws/src cd ~/calib_ws/src git clone https://github.com/acfr/cam_lidar_calibration cd .. catkin_make常见环境问题排查表问题现象可能原因解决方案编译时报Eigen错误Eigen库版本不兼容sudo apt install libeigen3-dev运行时缺少依赖未安装完整ROS包rosdep install --from-paths src --ignore-src -r -y相机话题不显示相机驱动未正确加载检查相机型号对应的ROS驱动包提示建议使用Ubuntu 18.04/20.04 LTS系统避免在非LTS版本上遇到兼容性问题2. 参数配置标定前的精细调整标定的精度很大程度上取决于配置文件的准确性。打开config/params.yaml这些关键参数需要特别注意camera: image_topic: /camera/image_raw # 必须与实际话题一致 camera_info_topic: /camera/camera_info distortion_model: plumb_bob lidar: pointcloud_topic: /lidar/points num_rings: 32 # 必须与雷达型号匹配三大易错点详解frame_id一致性检查所有传感器的frame_id是否统一不一致会导致坐标转换失败ring信息处理镭神C32等雷达需要手动添加ring信息可通过以下代码转换# 将PointXYZ转换为PointXYZIR格式 from sensor_msgs.msg import PointCloud2 import laser_geometry.laser_geometry as lg lp lg.LaserProjection() cloud_out lp.projectLaser(cloud_in)camera_info发布如果相机不自动发布该信息需要手动构造from sensor_msgs.msg import CameraInfo info CameraInfo() info.header.stamp rospy.Time.now() info.height 1080 # 根据实际分辨率调整 info.width 1920 pub.publish(info)3. 数据采集标定素材获取技巧优质的数据采集是成功标定的关键。建议采用以下工作流程棋盘格准备使用A4或更大尺寸的棋盘格确保棋盘格平面平整无弯曲背景环境尽量简单避免干扰点数据录制技巧每个位姿静止录制3-5秒至少采集10个不同位姿的数据使用以下命令录制rosbagrosbag record -O calibration.bag /camera/image_raw /lidar/points位姿布局建议棋盘格与雷达呈30-60度夹角包含俯仰、偏航等多种角度距离控制在2-5米范围内注意避免棋盘格与背景物体距离过近否则点云分割会受影响4. 标定执行分步操作指南一切就绪后让我们启动标定流程启动标定系统roslaunch cam_lidar_calibration cam_lidar_calibration.launchRVIZ参数调整打开rqt_reconfigure界面调整XYZ轴范围使点云仅保留棋盘格区域典型参数范围x_min: -1.0, x_max: 1.0 y_min: -1.0, y_max: 1.0 z_min: 0.1, z_max: 2.0数据采集流程点击Capture按钮采集当前帧更换棋盘格位姿或加载新rosbag重复至少5次不同位姿采集不满意时可点击Discard放弃当前帧优化执行采集足够样本后点击Optimize等待优化完成约1-5分钟结果将显示在终端并保存到文件标定结果解读 优化完成后会输出类似以下结果Rotation vector: [0.12, -0.05, 0.08] Translation: [0.35, -0.12, 0.25] Reprojection error: 0.8 pixels误差值小于2像素通常认为标定质量较好。5. 高级技巧与问题排查在实际项目中我们常遇到这些进阶问题点云分割不理想现象棋盘格点云包含背景杂点解决方案增大棋盘格与背景的距离使用统计离群值滤波预处理from pcl_helper import statistical_outlier_filter cloud_filtered statistical_outlier_filter(cloud, mean_k50, std_dev1.0)标定误差过大检查清单确认时间同步传感器时间戳偏差应小于0.1秒验证棋盘格角点检测是否准确检查至少使用了5个不同位姿的数据多传感器标定验证 完成标定后可通过以下代码验证结果import numpy as np from scipy.spatial.transform import Rotation as R # 将旋转向量转换为变换矩阵 r R.from_rotvec([0.12, -0.05, 0.08]) T np.eye(4) T[:3,:3] r.as_matrix() T[:3,3] [0.35, -0.12, 0.25] # 将雷达点转换到相机坐标系 def lidar_to_camera(point): p np.append(point, 1) return np.dot(T, p)[:3]最后分享一个实战经验在室外场景标定时早晨或傍晚的阳光角度能产生更清晰的棋盘格边缘检测效果。我曾在一个自动驾驶项目中通过调整标定时间将误差从3.2像素降低到1.5像素。

更多文章