现有一个ls c16和相机,需要进行联合标定
拿到手一个开源工具包 GitHub - Xujianhong123Allen/sensor_calibration
其中有相机和雷达联合标定的代码 cam_lidar_calibration
当我将其编译通过后却并不能直接使用
需要改的部分就是 camere_topic 和 lslidar_topic
yaml相机内参-----------需要自己标定
标定相机内参
rosrun camera_calibration cameracalibrator.py ––size 8x6 ––square 0.085 image:=/minibus/camera/0/image --no-service-check
注意:
1. topic时间戳应该是比较接近的,相差太远的话,可能无法进行同步,extractROI函数就不会工作
sync = new message_filters::Synchronizer<MySyncPolicy>(MySyncPolicy(5), *image_sub, *pcl_sub);
sync->registerCallback(boost::bind(&feature_extraction::extractROI, this, _1, _2));
消息同步机制,在代码中的 MySyncPolicy(5)
中,数字 5 表示同步队列的大小(queue size)。该数字指定了同步策略中用于缓存消息的队列的最大长度
同步队列的作用是在消息到达时临时存储消息,直到可以进行同步处理。如果消息到达的速度大于处理的速度,同步队列将会存储多个消息,并按照到达的顺序进行处理。如果队列已满且有新消息到达,则最早到达的消息将被丢弃。
因此,数字 5 表示同步队列的最大长度为 5。这意味着,当同步队列中存储了 5 条未处理的消息时,如果有新的消息到达,最早到达的消息将被丢弃,以便为新消息腾出空间。
选择适当的同步队列大小需要根据具体的应用场景和系统需求进行调整。较大的队列大小可以缓存更多的消息,但会增加内存消耗和处理延迟。较小的队列大小可以减小延迟,但可能会导致消息丢失风险。因此,根据系统的实际情况和性能要求,选择合适的队列大小是很重要的。
2. [ERROR] [1688720996.772985773]: PATTERN NOT FOUND
相机角点提取不到,这可能与我的一下参数设置有关了,检查标定版参数,角点数量,是否标定板离相机的距离太远等等
3. 在采集simple时有时会报错,导致程序退出,之前采集的样本也没了,因此需要搞明白为什么会出现这种情况???
[pcl::SampleConsensusModel::getSamples] Can not select 0 unique points out of 1! [pcl::RandomSampleConsensus::computeModel] No samples could be selected! [pcl::RandomSampleConsensus::computeModel] RANSAC found no model. [pcl::SACSegmentation::segment] Error segmenting the model! No solution found. [pcl::SampleConsensusModel::getSamples] Can not select 0 unique points out of 1! [pcl::RandomSampleConsensus::computeModel] No samples could be selected! [pcl::RandomSampleConsensus::computeModel] RANSAC found no model. [pcl::SACSegmentation::segment] Error segmenting the model! No solution found.
上述问题,可能是我采集数据时,没有注意
数据采集时应注意 雷达和相机能扫到完整的标定板,否则容易出现拟合失败,直接退出程序
当我重新采集15个数据后发现基本都可以,因此录制数据集是应该保证其质量
同时在采集样本时应该取其拟合效果较好的,输入i后会看到拟合平面,有的时候拟合效果很不好,此时不要输入 enter,继续输入 i,直到拟合效果看起来
如图:
左图明显有问题,因此需要重新采集simple(输入i),直到如右图这样,再按 enter
经过15次simple的收集,按下o,进行优化
会得到一个存放标定文件的yaml
roslaunch cam_lidar_calibration project_img.launch
将project_img.launch文件里的yaml改为自己标定得到的yaml
就可以看到自己标定出来的结果了
这个结果看起来挺好的,但是雷达的扫描应该是覆盖整个图像宽度的,但是这个映射出来的点云图像,好像图像左边有一部分没扫描到。
初步怀疑是相机畸变矫正部分没有做好?在显示的时候输入畸变后的图像,将点云投影到畸变后的图像上。
去畸变后仍然是这样,后来发现是与该参数有关 std::abs(tmpxC) <= 2.35
std::abs(tmpxC) <= 2.35
:映射点的归一化 x 坐标绝对值小于等于 2.35。
总结标定流程:
1. 标定相机内参,并将其参数填进 initial_params.yaml
2. 标定板参数设置(角点数量,squareLength等)代码的readme文件有详细说明
3. bag包录制(注意距离和高度应在相机和雷达接受范围之内)
4. 播放bag 采集样本进行标定
话题我进行了一个转化,命令如下
rosbag play cam_lidar-1.bag /minibus/camera/0/image:=/camera/color/image_raw /lslidar_c16_point_cloud:=/velodyne_points -l
我有15个bag 每个bag取一个样本
bag我后期会考虑传到百度网盘上供大家尝试